verify-instanced-coarse-pilot.mjs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940
  1. import assert from 'node:assert/strict'
  2. import { readFileSync, existsSync } from 'node:fs'
  3. import { resolve, join } from 'node:path'
  4. const dir = resolve(process.argv[2] || 'tools/city-massing/city/cad-bim/instanced-coarse-pilot-v1')
  5. const report = JSON.parse(readFileSync(join(dir, 'manifest.json'), 'utf8'))
  6. const tree = JSON.parse(readFileSync(join(dir, 'tileset.json'), 'utf8'))
  7. assert.equal(report.candidateOnly, true)
  8. assert.equal(report.buildings, 13)
  9. assert.equal(tree.root.children.length, report.records.length)
  10. const ids = new Set(), files = new Set()
  11. let instances = 0, bytes = 0
  12. for (const record of report.records) {
  13. assert.equal(record.buildingIds.length, new Set(record.buildingIds).size)
  14. for (const id of record.buildingIds) { assert.ok(!ids.has(id), `duplicate ${id}`); ids.add(id) }
  15. const path = join(dir, record.uri), glb = readFileSync(path)
  16. assert.ok(!files.has(record.uri)); files.add(record.uri); assert.equal(glb.length, record.bytes); bytes += glb.length
  17. assert.equal(glb.toString('ascii', 0, 4), 'glTF'); assert.equal(glb.readUInt32LE(4), 2); assert.equal(glb.readUInt32LE(8), glb.length)
  18. const jsonLength = glb.readUInt32LE(12), json = JSON.parse(glb.toString('utf8', 20, 20 + jsonLength))
  19. assert.deepEqual(json.extensionsRequired, ['EXT_mesh_gpu_instancing'])
  20. assert.equal(json.nodes[0].children.length, json.nodes.length - 1)
  21. let extensionNodes = 0
  22. for (const node of json.nodes.slice(1)) {
  23. const ext = node.extensions?.EXT_mesh_gpu_instancing
  24. if (!ext) continue
  25. extensionNodes++
  26. const attrs = ext.attributes
  27. assert.ok(Number.isInteger(attrs.TRANSLATION) && Number.isInteger(attrs.ROTATION) && Number.isInteger(attrs.SCALE))
  28. const count = json.accessors[attrs.TRANSLATION].count
  29. assert.equal(json.accessors[attrs.ROTATION].count, count)
  30. assert.equal(json.accessors[attrs.SCALE].count, count)
  31. assert.equal(node.extras.buildingIds.length, count)
  32. instances += count
  33. }
  34. assert.ok(extensionNodes > 0)
  35. assert.ok(json.extensionsUsed.includes('EXT_mesh_gpu_instancing'))
  36. assert.ok(json.meshes.length > 0)
  37. assert.ok(json.images === undefined)
  38. }
  39. assert.equal(ids.size, 13); assert.equal(instances, report.records.reduce((n, r) => n + r.instanceCount, 0)); assert.equal(bytes, report.records.reduce((n, r) => n + r.bytes, 0))
  40. console.log(JSON.stringify({ passed: true, buildings: ids.size, files: files.size, instances, bytes, caveat: 'offline GLB structure only; no Cesium traversal or FPS validation' }))