// Build a valid empty-scene GLB so Cesium can traverse a contentless spatial root reliably. import { Buffer } from 'node:buffer' import { mkdirSync, writeFileSync } from 'node:fs' import { resolve } from 'node:path' const json = Buffer.from(JSON.stringify({ asset: { version: '2.0', generator: 'ticket35 root anchor' }, scene: 0, scenes: [{ nodes: [] }], })) const padded = Buffer.concat([json, Buffer.alloc((4 - json.length % 4) % 4, 0x20)]) const header = Buffer.alloc(12) header.write('glTF') header.writeUInt32LE(2, 4) header.writeUInt32LE(12 + 8 + padded.length, 8) const chunk = Buffer.alloc(8) chunk.writeUInt32LE(padded.length) chunk.write('JSON', 4) const glb = Buffer.concat([header, chunk, padded]) if (glb.readUInt32LE(8) !== glb.length || glb.toString('ascii', 16, 20) !== 'JSON') { throw new Error('Invalid GLB header') } JSON.parse(glb.toString('utf8', 20, 20 + glb.readUInt32LE(12))) for (const dir of ['tools/city-massing/district/lod-preview', 'tools/city-massing/city/regular-estate/lod-preview', 'tools/city-massing/city/oldtown/lod-preview']) { mkdirSync(resolve(dir), { recursive: true }) writeFileSync(resolve(dir, 'root-anchor.glb'), glb) } console.log({ bytes: glb.length, outputs: 3 })