mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-14 23:32:20 +00:00
Merge pull request #1731 from bilawalsidhu/fleet/aircraft-mesh-colours
Draw aircraft models in their own mesh colours
This commit is contained in:
14 files changed
+61
-61
No files matched your search
@@ -0,0 +1,3 @@
|
||||
- Draw aircraft models in their own mesh colours instead of a 94% flat
|
||||
white (amber for military) over the model; the tracked and emergency
|
||||
colours now tint the mesh without hiding its paint (samehkhamis, #1731).
|
||||
@@ -7429,9 +7429,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. Every model is one of the project's procedural fleet models (`public/models/fleet/`, MIT, 122 GLBs, about 2 MB in all; `public/models/README.md`), chosen per aircraft by `aircraftModelSpec` (`src/data/fleetModels.js`): the first of its ICAO type's callsign rules in `types.json` (`aircraft_callsign`) its callsign matches, else its type's entry, 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. An airport ground vehicle (feed type `ZVEH`) is a fire truck (`FIRE…`), pushback tug (`PUSH…`, `TUG…`), van (`DEICER…`, `SQUID…`, `SQB…`) or else a car by its callsign, and a ground station (`GRND`) is an 11.8 m radio mast; these models (catalog category `other`) are drawn at their built size, and such a contact with no altitude stands on the ground instead of at the airborne default (`src/layers/flights/records.js`). `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/122 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.
|
||||
- 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, 122 GLBs, about 2 MB in all; `public/models/README.md`), chosen per aircraft by `aircraftModelSpec` (`src/data/fleetModels.js`): the first of its ICAO type's callsign rules in `types.json` (`aircraft_callsign`) its callsign matches, else its type's entry, 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. An airport ground vehicle (feed type `ZVEH`) is a fire truck (`FIRE…`), pushback tug (`PUSH…`, `TUG…`), van (`DEICER…`, `SQUID…`, `SQB…`) or else a car by its callsign, and a ground station (`GRND`) is an 11.8 m radio mast; these models (catalog category `other`) are drawn at their built size, and such a contact with no altitude stands on the ground instead of at the airborne default (`src/layers/flights/records.js`). `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/122 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. Every aircraft model draws its mesh's own colours (`aircraftModelBlend`, `src/data/aircraftModelLighting.js`): Cesium's `ColorBlendMode.HIGHLIGHT` with white, in Flights, Military Flights and Local ADS-B alike; the tracked colour (cyan, or amber in Military Flights) and the emergency red multiply into the mesh, so its paint still shows. IR boost draws them flat white (`MIX` at `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.
|
||||
- **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). 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.
|
||||
|
||||
@@ -458,7 +458,8 @@ test('tint priorities cover normal, priority, emergency, tracking and Cockpit do
|
||||
);
|
||||
flightState._trackedIcao = null;
|
||||
flightState.records.data.set('civil', { emergency: null });
|
||||
assert.equal(rendering._modelColor('civil'), normal);
|
||||
// An ordinary model draws its mesh's own colours, whatever the billboard's.
|
||||
assert.equal(rendering._modelColor('civil'), Cesium.Color.WHITE);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import * as Cesium from 'cesium';
|
||||
|
||||
/**
|
||||
* Lighting options shared by every aircraft 3D model (Flights, Military
|
||||
* Flights, Local ADS-B).
|
||||
@@ -6,12 +8,24 @@
|
||||
* the model and reads the result back from the GPU (`readPixels`) to light it,
|
||||
* when the model is first placed and again when it moves more than 1 km, when
|
||||
* the scene's atmosphere settings change, or every scene hour under sunlight
|
||||
* lighting. Aircraft models take 94% of their surface from the class colour
|
||||
* (`colorBlendAmount`), so that lighting contributes little; without it they
|
||||
* are lit from Cesium's default spherical harmonics. Measured 2026-10-24
|
||||
* (Intel Arc, Google 3D, ~150 models in the scene): GPU per frame at rest
|
||||
* 14.3-14.8 -> 12.1-12.5 ms.
|
||||
* lighting. Without it they are lit from Cesium's default spherical
|
||||
* harmonics. Measured 2026-10-24 (Intel Arc, Google 3D, ~150 models in the
|
||||
* scene): GPU per frame at rest 14.3-14.8 -> 12.1-12.5 ms.
|
||||
*/
|
||||
export const AIRCRAFT_ENVIRONMENT_MAP_OPTIONS = Object.freeze({
|
||||
enabled: false,
|
||||
});
|
||||
|
||||
/**
|
||||
* How an aircraft model's colour meets its mesh. HIGHLIGHT multiplies, so
|
||||
* white draws the mesh's own colours as built, and the tracked or emergency
|
||||
* colour tints the mesh without hiding its paint. The IR boost draws the
|
||||
* model flat white instead (MIX at 1, with its unlit shader).
|
||||
* @param {boolean} irBoost
|
||||
* @returns {{colorBlendMode: Cesium.ColorBlendMode, colorBlendAmount: number}}
|
||||
*/
|
||||
export function aircraftModelBlend(irBoost) {
|
||||
return irBoost
|
||||
? { colorBlendMode: Cesium.ColorBlendMode.MIX, colorBlendAmount: 1 }
|
||||
: { colorBlendMode: Cesium.ColorBlendMode.HIGHLIGHT, colorBlendAmount: 0 };
|
||||
}
|
||||
@@ -243,7 +243,7 @@ export function applyAircraftBillboardTreatment({
|
||||
|
||||
/**
|
||||
* Apply layer-owned hue and composed aircraft alpha to an ambient glTF model without
|
||||
* disturbing Cesium's existing MIX/colorBlendAmount presentation semantics.
|
||||
* changing the model's colour blend mode or amount.
|
||||
* @param {object} input
|
||||
* @param {object} input.model
|
||||
* @param {{withAlpha:(alpha:number)=>object}} input.baseColor
|
||||
|
||||
@@ -291,7 +291,7 @@ test('tracking layers write gevLabelModel and expose only their cached display p
|
||||
assert.equal(sources['satellites.js'].includes('_trackedEntity.label.text'), false);
|
||||
});
|
||||
|
||||
test('civilian and military trail heads use the lower-centre model anchor and weak-texture tint', async () => {
|
||||
test('civilian and military trail heads use the lower-centre model anchor', async () => {
|
||||
const files = await Promise.all(['flights.js', 'militaryFlights.js'].map(async (name) => (
|
||||
[name, readLayerSource(new URL(`./${name}`, import.meta.url))]
|
||||
)));
|
||||
@@ -300,7 +300,5 @@ test('civilian and military trail heads use the lower-centre model anchor and we
|
||||
(/const\s*head\s*=\s*(?:parts\.motion\.)?_trackedTrailCached\(\s*,?\s*\)\s*\|\|\s*(?:parts\.motion\.)?_trackedDisplayPosition\(\s*(?:flightState\.)?_trackedIcao,?\s*\);/).test(source),
|
||||
`${name} trail head uses the dedicated lower-centre model anchor`,
|
||||
);
|
||||
assert.ok(source.includes('const MODEL_COLOR_BLEND_AMOUNT = 0.94;'),
|
||||
`${name} keeps diffuse texture contribution weak through code-side MIX`);
|
||||
}
|
||||
});
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
aircraftModelSpec,
|
||||
fleetModelSet,
|
||||
} from '../../data/fleetModels.js';
|
||||
import { MODEL_COLOR_BLEND_AMOUNT } from './policy.js';
|
||||
|
||||
/**
|
||||
* What an aircraft draws with before the fleet model set has loaded: no
|
||||
@@ -22,7 +21,6 @@ export const UNLOADED_AIRCRAFT_MODEL_SPEC = Object.freeze({
|
||||
bellyM: 0,
|
||||
elevationM: 0,
|
||||
tinted: false,
|
||||
blendAmount: MODEL_COLOR_BLEND_AMOUNT,
|
||||
visualCenterNative: Object.freeze([0, 0, 0]),
|
||||
trailAnchorNative: Object.freeze([0, 0, 0]),
|
||||
key: 'unloaded',
|
||||
@@ -58,7 +56,6 @@ export function aircraftLayerModelSpec(aircraft, set = fleetModelSet()) {
|
||||
layerSpec = Object.freeze({
|
||||
...spec,
|
||||
bellyM: spec.clearanceM,
|
||||
blendAmount: MODEL_COLOR_BLEND_AMOUNT,
|
||||
});
|
||||
cache.set(key, layerSpec);
|
||||
}
|
||||
|
||||
@@ -85,10 +85,6 @@ export const MODEL_ALL_KEEP_M = 450000;
|
||||
|
||||
export const MODEL_HEADING_OFFSET_DEG = 180;
|
||||
// every fleet model is nose -X: opposite Cesium heading 0
|
||||
// Owner launch-polish direction: models should read as clean light silhouettes,
|
||||
// with only a weak diffuse contribution from the models' own colours.
|
||||
|
||||
export const MODEL_COLOR_BLEND_AMOUNT = 0.94;
|
||||
|
||||
export const CYAN_TRANSPARENT = Cesium.Color.CYAN.withAlpha(0);
|
||||
|
||||
|
||||
@@ -45,7 +45,10 @@ import {
|
||||
STALE_ALPHA,
|
||||
displayDelayMs,
|
||||
} from './policy.js';
|
||||
import { AIRCRAFT_ENVIRONMENT_MAP_OPTIONS } from '../../data/aircraftModelLighting.js';
|
||||
import {
|
||||
AIRCRAFT_ENVIRONMENT_MAP_OPTIONS,
|
||||
aircraftModelBlend,
|
||||
} from '../../data/aircraftModelLighting.js';
|
||||
|
||||
export function createRendering({
|
||||
flightState,
|
||||
@@ -192,11 +195,12 @@ export function createRendering({
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
/** Model tint, mirroring the billboard color rules. */
|
||||
/** Model colour: the mesh's own (white), tinted cyan while tracked and red
|
||||
* while broadcasting an emergency. */
|
||||
|
||||
function _modelColor(icao24) {
|
||||
if (icao24 === flightState._trackedIcao) return Cesium.Color.CYAN;
|
||||
return _fleetBillboardColor(icao24);
|
||||
return _isEmergency(icao24) ? EMERGENCY_TINT : Cesium.Color.WHITE;
|
||||
}
|
||||
|
||||
/** The FLEET's 3D-model regime: models3d enabled AND the camera zoomed in past the altitude
|
||||
@@ -526,10 +530,7 @@ export function createRendering({
|
||||
minimumPixelSize: MODEL_MIN_PX,
|
||||
scale: spec.scale,
|
||||
color: flightState._irBoost ? Cesium.Color.WHITE : _modelColor(icao24),
|
||||
colorBlendMode: Cesium.ColorBlendMode.MIX,
|
||||
// Launch presentation keeps the code-side tint dominant for every approved
|
||||
// model; IR boost removes the remaining diffuse hint with flat UNLIT white.
|
||||
colorBlendAmount: flightState._irBoost ? 1.0 : spec.blendAmount,
|
||||
...aircraftModelBlend(flightState._irBoost),
|
||||
customShader: flightState._irBoost
|
||||
? flightState._IR_UNLIT_SHADER
|
||||
: undefined,
|
||||
@@ -748,10 +749,7 @@ export function createRendering({
|
||||
minimumPixelSize: TRACKED_MODEL_MIN_PX,
|
||||
scale: trackedSpec.scale,
|
||||
color: flightState._irBoost ? Cesium.Color.WHITE : Cesium.Color.CYAN,
|
||||
colorBlendMode: Cesium.ColorBlendMode.MIX,
|
||||
// The tracked aircraft uses the same dominant light tint as the fleet;
|
||||
// IR boost removes the remaining diffuse hint with flat UNLIT white.
|
||||
colorBlendAmount: flightState._irBoost ? 1.0 : trackedSpec.blendAmount,
|
||||
...aircraftModelBlend(flightState._irBoost),
|
||||
customShader: flightState._irBoost
|
||||
? flightState._IR_UNLIT_SHADER
|
||||
: undefined,
|
||||
|
||||
@@ -700,7 +700,6 @@ export function createLocalAdsbLayer({
|
||||
if (viewer.scene?.primitives) {
|
||||
models = createLocalAdsbModels({
|
||||
viewer,
|
||||
color,
|
||||
resolveAsset,
|
||||
groundSnap: services.groundSnap?.createGroundSnap?.() || null,
|
||||
...(loadModel ? { loadModel } : {}),
|
||||
|
||||
@@ -503,7 +503,7 @@ test('adsbdb type, operator and route reach the card for the selected aircraft o
|
||||
assert.equal(queries.length, 2, 'each key is asked for once');
|
||||
});
|
||||
|
||||
test('the DISPLAY 3D toggle gives local aircraft magenta class models', async (t) => {
|
||||
test('the DISPLAY 3D toggle gives local aircraft their fleet models in their mesh colours', async (t) => {
|
||||
const receiver = fakeReceiver({ mode: 'adsb', connected: true });
|
||||
const clock = { now: 100_000 };
|
||||
const loads = [];
|
||||
@@ -548,13 +548,10 @@ test('the DISPLAY 3D toggle gives local aircraft magenta class models', async (t
|
||||
assert.equal(model.scale, spec.scale, 'drawn life size');
|
||||
assert.equal(model.id, 'local-adsb:a0b702');
|
||||
assert.ok(
|
||||
Cesium.Color.equals(
|
||||
model.color,
|
||||
Cesium.Color.fromCssColorString('#ff4fd8'),
|
||||
),
|
||||
Cesium.Color.equals(model.color, Cesium.Color.WHITE),
|
||||
'the mesh draws its own colours',
|
||||
);
|
||||
assert.equal(model.colorBlendMode, Cesium.ColorBlendMode.MIX);
|
||||
assert.equal(model.colorBlendAmount, 0.94);
|
||||
assert.equal(model.colorBlendMode, Cesium.ColorBlendMode.HIGHLIGHT);
|
||||
assert.equal(model.show, true);
|
||||
const heli = sources[0].entities.getById('local-adsb:a0b702');
|
||||
assert.equal(
|
||||
|
||||
@@ -16,7 +16,10 @@ import {
|
||||
MODEL_PROX_ADD_M,
|
||||
MODEL_PROX_KEEP_M,
|
||||
} from '../flights/policy.js';
|
||||
import { AIRCRAFT_ENVIRONMENT_MAP_OPTIONS } from '../../data/aircraftModelLighting.js';
|
||||
import {
|
||||
AIRCRAFT_ENVIRONMENT_MAP_OPTIONS,
|
||||
aircraftModelBlend,
|
||||
} from '../../data/aircraftModelLighting.js';
|
||||
|
||||
const specOf = (marker) =>
|
||||
aircraftLayerModelSpec({
|
||||
@@ -31,15 +34,14 @@ const specOf = (marker) =>
|
||||
* Mirrors the public Flights fleet: models only below the altitude ceiling,
|
||||
* the same proximity/all caps and add/keep radii, the same visible-first
|
||||
* eligibility (`selectModelEligible`), the same fleet model per type, life
|
||||
* size (`aircraftLayerModelSpec`) and the same tint path (a MIX colour blend, here
|
||||
* magenta, as Flights tints military amber). Each model owns its matrix. A
|
||||
* size (`aircraftLayerModelSpec`) and the same colours: the mesh's own
|
||||
* (`aircraftModelBlend`). Each model owns its matrix. A
|
||||
* billboard stays the visual until its model is loaded AND placed; a grounded
|
||||
* aircraft's model rides the one-shot ground snap plus the class belly
|
||||
* offset, and without a resolved ground it stays a billboard. Every fleet
|
||||
* model loads once, up front, when the layer starts (`loadFleetModelSet`).
|
||||
* @param {object} options
|
||||
* @param {object} options.viewer Cesium viewer.
|
||||
* @param {Cesium.Color} options.color Model tint.
|
||||
* @param {(url: string) => string} options.resolveAsset
|
||||
* @param {object|null} [options.groundSnap] `createGroundSnap()` instance.
|
||||
* @param {(options: object) => Promise<object>} [options.loadModel]
|
||||
@@ -47,7 +49,6 @@ const specOf = (marker) =>
|
||||
*/
|
||||
export function createLocalAdsbModels({
|
||||
viewer,
|
||||
color,
|
||||
resolveAsset,
|
||||
groundSnap = null,
|
||||
loadModel = (options) => Cesium.Model.fromGltfAsync(options),
|
||||
@@ -104,9 +105,8 @@ export function createLocalAdsbModels({
|
||||
environmentMapOptions: AIRCRAFT_ENVIRONMENT_MAP_OPTIONS,
|
||||
minimumPixelSize: MODEL_MIN_PX,
|
||||
scale: spec.scale,
|
||||
color,
|
||||
colorBlendMode: Cesium.ColorBlendMode.MIX,
|
||||
colorBlendAmount: spec.blendAmount,
|
||||
color: Cesium.Color.WHITE,
|
||||
...aircraftModelBlend(false),
|
||||
id,
|
||||
},
|
||||
{ resolveAsset, load: loadModel },
|
||||
|
||||
@@ -107,10 +107,6 @@ export const MODEL_ALL_KEEP_M = 450000;
|
||||
|
||||
export const MODEL_HEADING_OFFSET_DEG = 180;
|
||||
// every fleet model is nose -X: opposite Cesium heading 0
|
||||
// Preserve the layer's amber identity while reducing the models' own colours
|
||||
// to a weak diffuse hint, matching civilian launch presentation.
|
||||
|
||||
export const MODEL_COLOR_BLEND_AMOUNT = 0.94;
|
||||
|
||||
/** Amber fade target for the tracked billboard once the model takes over (mirrors flights.js CYAN_TRANSPARENT). */
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ import {
|
||||
MODEL_PROX_KEEP_M,
|
||||
IR_RELOAD_BATCH,
|
||||
MODEL_MIN_PX,
|
||||
MODEL_COLOR_BLEND_AMOUNT,
|
||||
TRACKED_MODEL_MIN_PX,
|
||||
TRACKED_MODEL_MAX_PX,
|
||||
FLEET_DR_INTERVAL_MS,
|
||||
@@ -43,7 +42,10 @@ import {
|
||||
COURSE_MAX_DPS,
|
||||
STALE_ALPHA,
|
||||
} from './policy.js';
|
||||
import { AIRCRAFT_ENVIRONMENT_MAP_OPTIONS } from '../../data/aircraftModelLighting.js';
|
||||
import {
|
||||
AIRCRAFT_ENVIRONMENT_MAP_OPTIONS,
|
||||
aircraftModelBlend,
|
||||
} from '../../data/aircraftModelLighting.js';
|
||||
|
||||
export function createRendering({
|
||||
flightState,
|
||||
@@ -81,7 +83,6 @@ export function createRendering({
|
||||
const base = aircraftLayerModelSpec(meta);
|
||||
spec = Object.freeze({
|
||||
...base,
|
||||
blendAmount: MODEL_COLOR_BLEND_AMOUNT,
|
||||
headingOffsetDeg: MODEL_HEADING_OFFSET_DEG,
|
||||
});
|
||||
// Not cached before the model set loads: the answer changes once it has.
|
||||
@@ -152,11 +153,15 @@ export function createRendering({
|
||||
const _iconKind = (icao24, klass) =>
|
||||
tr3bIconKind(icao24, klass, { hot: flightState._irBoost });
|
||||
|
||||
/** Model tint, mirroring the billboard color rules (amber instead of cyan/white). */
|
||||
/** Model colour: the mesh's own (white), tinted amber while tracked and red
|
||||
* while broadcasting an emergency. */
|
||||
|
||||
function _modelColor(icao24) {
|
||||
if (icao24 === flightState._trackedIcao) return TRACKED_ICON_COLOR;
|
||||
return _fleetBillboardColor(icao24);
|
||||
const info = flightState.records.data.get(icao24);
|
||||
return isEmergency(info?.emergency)
|
||||
? EMERGENCY_ICON_COLOR
|
||||
: Cesium.Color.WHITE;
|
||||
}
|
||||
|
||||
/** Fleet (untracked) tint: red while the latest poll broadcast an emergency,
|
||||
@@ -443,9 +448,7 @@ export function createRendering({
|
||||
minimumPixelSize: MODEL_MIN_PX,
|
||||
scale: spec.scale,
|
||||
color: flightState._irBoost ? Cesium.Color.WHITE : _modelColor(icao24),
|
||||
colorBlendMode: Cesium.ColorBlendMode.MIX,
|
||||
// near self-illuminated tint so planes read uniform near AND far; IR boost → flat UNLIT white (hot)
|
||||
colorBlendAmount: flightState._irBoost ? 1.0 : MODEL_COLOR_BLEND_AMOUNT,
|
||||
...aircraftModelBlend(flightState._irBoost),
|
||||
customShader: flightState._irBoost
|
||||
? flightState._IR_UNLIT_SHADER
|
||||
: undefined,
|
||||
@@ -662,9 +665,7 @@ export function createRendering({
|
||||
minimumPixelSize: TRACKED_MODEL_MIN_PX,
|
||||
scale: trackedSpec.scale,
|
||||
color: flightState._irBoost ? Cesium.Color.WHITE : TRACKED_ICON_COLOR,
|
||||
colorBlendMode: Cesium.ColorBlendMode.MIX,
|
||||
// near self-illuminated tint so planes read uniform near AND far; IR boost → flat UNLIT white (hot)
|
||||
colorBlendAmount: flightState._irBoost ? 1.0 : MODEL_COLOR_BLEND_AMOUNT,
|
||||
...aircraftModelBlend(flightState._irBoost),
|
||||
customShader: flightState._irBoost
|
||||
? flightState._IR_UNLIT_SHADER
|
||||
: undefined,
|
||||
|
||||
Reference in new issue
Block a user