make-root-anchor.mjs 1.2 KB

123456789101112131415161718192021222324252627
  1. // Build a valid empty-scene GLB so Cesium can traverse a contentless spatial root reliably.
  2. import { Buffer } from 'node:buffer'
  3. import { mkdirSync, writeFileSync } from 'node:fs'
  4. import { resolve } from 'node:path'
  5. const json = Buffer.from(JSON.stringify({
  6. asset: { version: '2.0', generator: 'ticket35 root anchor' },
  7. scene: 0,
  8. scenes: [{ nodes: [] }],
  9. }))
  10. const padded = Buffer.concat([json, Buffer.alloc((4 - json.length % 4) % 4, 0x20)])
  11. const header = Buffer.alloc(12)
  12. header.write('glTF')
  13. header.writeUInt32LE(2, 4)
  14. header.writeUInt32LE(12 + 8 + padded.length, 8)
  15. const chunk = Buffer.alloc(8)
  16. chunk.writeUInt32LE(padded.length)
  17. chunk.write('JSON', 4)
  18. const glb = Buffer.concat([header, chunk, padded])
  19. if (glb.readUInt32LE(8) !== glb.length || glb.toString('ascii', 16, 20) !== 'JSON') {
  20. throw new Error('Invalid GLB header')
  21. }
  22. JSON.parse(glb.toString('utf8', 20, 20 + glb.readUInt32LE(12)))
  23. 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']) {
  24. mkdirSync(resolve(dir), { recursive: true })
  25. writeFileSync(resolve(dir, 'root-anchor.glb'), glb)
  26. }
  27. console.log({ bytes: glb.length, outputs: 3 })