| 12345678910111213141516171819202122232425262728293031 |
- import assert from 'node:assert/strict'
- // Streaming exporter supports standard embedded-raster textures, not extension image sources.
- export function verifyMaterialClosure(json, label = 'GLB') {
- const materials = json.materials || [], textures = json.textures || [], images = json.images || [], samplers = json.samplers || []
- const usedMaterials = new Set(), usedTextures = new Set(), usedImages = new Set(), usedSamplers = new Set()
- function reference(index, values, kind, used) {
- assert.ok(Number.isInteger(index) && index >= 0 && index < values.length, `${label}: invalid ${kind} index ${index}`)
- used.add(index)
- }
- for (const mesh of json.meshes || []) for (const primitive of mesh.primitives) {
- reference(primitive.material, materials, 'material', usedMaterials)
- }
- function visit(value) {
- for (const [key, child] of Object.entries(value)) {
- if (!child || typeof child !== 'object') continue
- if (key.endsWith('Texture')) reference(child.index, textures, 'texture', usedTextures)
- else visit(child)
- }
- }
- for (const index of usedMaterials) visit(materials[index])
- for (const index of usedTextures) {
- const texture = textures[index]
- reference(texture.source, images, 'image', usedImages)
- if (texture.sampler !== undefined) reference(texture.sampler, samplers, 'sampler', usedSamplers)
- }
- for (const [kind, used, values] of [['materials', usedMaterials, materials], ['textures', usedTextures, textures],
- ['images', usedImages, images], ['samplers', usedSamplers, samplers]]) {
- assert.equal(used.size, values.length, `${label}: unused ${kind}`)
- }
- }
|