#!/usr/bin/env node // Comprime con Draco un modello GLB: node scripts/comprimi-glb.mjs // // Usato dal backoffice al caricamento di un modello 3D (App\Support\Configuratore\CompressoreGlb): // l'originale resta salvato non compresso, nel configuratore va solo questa copia. Nel browser la // decomprime il DRACOLoader di three.js (vedi src/js/starter.js). // // In caso di successo stampa su stdout una riga JSON con le dimensioni prima/dopo. import fs from 'node:fs/promises'; import { NodeIO } from '@gltf-transform/core'; import { ALL_EXTENSIONS } from '@gltf-transform/extensions'; import { draco, weld } from '@gltf-transform/functions'; import draco3d from 'draco3dgltf'; // Bit di quantizzazione: valori più alti = più fedeltà e file più grandi. // Le posizioni a 14 bit sono sotto il decimo di millimetro sulle dimensioni di un infisso. export const DRACO_OPTIONS = { method: 'edgebreaker', encodeSpeed: 5, decodeSpeed: 5, quantizePosition: 14, quantizeNormal: 10, quantizeTexcoord: 12, quantizeColor: 8, quantizeGeneric: 12, }; const [src, dest] = process.argv.slice(2); if (!src || !dest) { console.error('Uso: comprimi-glb.mjs '); process.exit(2); } try { const io = new NodeIO().registerExtensions(ALL_EXTENSIONS).registerDependencies({ 'draco3d.encoder': await draco3d.createEncoderModule(), 'draco3d.decoder': await draco3d.createDecoderModule(), }); const input = await fs.readFile(src); const doc = await io.readBinary(new Uint8Array(input)); if (!doc.getRoot().listMeshes().length) throw new Error('Il file non contiene geometrie.'); // Draco lavora su primitive indicizzate: weld unisce solo i vertici identici in tutti gli // attributi (posizione, normale, uv...), quindi non cambia l'aspetto del modello. await doc.transform(weld(), draco(DRACO_OPTIONS)); const output = await io.writeBinary(doc); await fs.writeFile(dest, output); console.log(JSON.stringify({ originale: input.length, compresso: output.length })); } catch (err) { console.error(err?.message ?? String(err)); process.exit(1); }