Files
gods-eye-view/scripts/measure-fleet-trail-anchors.mjs
T
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

54 lines
2.0 KiB
JavaScript

#!/usr/bin/env node
/**
* Re-measure the trail attachment point of every aircraft-layer fleet model
* and print `src/data/fleetTrailAnchors.js`.
*
* node scripts/measure-fleet-trail-anchors.mjs > src/data/fleetTrailAnchors.js
*
* Run it whenever a model under `public/models/fleet/` changes; the unit
* suite (`src/data/fleetModels.test.mjs`) re-derives each value and fails
* on a table that no longer matches its GLB.
*/
import fs from 'node:fs';
import path from 'node:path';
import { projectRoot } from './project-root.mjs';
import {
fleetMesh,
measuredTrailAnchor,
} from '../src/testSupport/fleetGlb.mjs';
/** Catalog categories the aircraft layers draw (ADS-B ground vehicles and balloons included). */
export const TRAIL_ANCHOR_CATEGORIES = ['aircraft', 'helicopters', 'other'];
const root = projectRoot(import.meta.url);
const dir = path.join(root, 'public', 'models', 'fleet');
const catalog = JSON.parse(
fs.readFileSync(path.join(dir, 'catalog.json'), 'utf8'),
);
const rows = [];
for (const [name, model] of Object.entries(catalog)) {
if (!TRAIL_ANCHOR_CATEGORIES.includes(model.category)) continue;
const anchor = measuredTrailAnchor(
await fleetMesh(path.join(dir, model.file)),
);
if (!anchor) continue;
const [x, y] = anchor.map((value) => Number(value.toFixed(4)) || 0);
rows.push(
` ${/^[a-z_]\w*$/.test(name) ? name : `'${name}'`}: Object.freeze([${x}, ${y}, 0]),`,
);
}
process.stdout.write(`/**
* Aft-belly trail attachment points of the fleet models the aircraft layers
* draw, in raw glTF axes (X along the body, nose toward -X; Y up), metres
* before scale, node transforms applied. Each is the point of the model's
* centreline profile (its z = 0 slice) nearest its aft-belly bounding-box
* corner: on the hull, aft, and on the centreline (see modelVisualAnchor.js).
*
* Written by scripts/measure-fleet-trail-anchors.mjs; re-measured against the
* GLBs by fleetModels.test.mjs.
*/
export const FLEET_TRAIL_ANCHORS = Object.freeze({
${rows.join('\n')}
});
`);