Come esportare scene 3D in glTF/GLB con TypeScript

Come esportare scene 3D in glTF/GLB con TypeScript

Aspose.3D FOSS supporta glTF 2.0 sia come formato di importazione che di esportazione. Lo stesso Scene oggetto può essere popolato da un file OBJ, FBX, STL o da un altro file sorgente e quindi scritto in .gltf (JSON + binario esterno) o .glb (contenitore binario unico) impostando una sola opzione su GltfSaveOptions.

Guida passo-passo

Passo 1: Installa @aspose/3d

npm install @aspose/3d

Conferma che Node.js 18 o versioni successive sia attivo:

node --version   # must be >= 16.0.0

Passo 2: Importa Scene, GltfSaveOptions e GltfFormat

import { Scene } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';

GltfFormat è il descrittore del formato passato a scene.save(). GltfSaveOptions contiene tutta la configurazione di esportazione.

Se stai anche caricando un file di origine (ad es., OBJ), importa le opzioni di caricamento corrispondenti:

import { ObjLoadOptions } from '@aspose/3d/formats/obj';

Passo 3: Crea o carica una scena

Opzione A: Carica da un file esistente (conversione OBJ → GLB):

import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';

const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());

Opzione B: Crea una scena minima programmaticamente:

import { Scene, Node, Mesh } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';

const scene = new Scene();
const childNode = new Node('cube');
scene.rootNode.addChildNode(childNode);
// Attach geometry to childNode as needed

Passo 4: Configura GltfSaveOptions

GltfSaveOptions controlla il formato di output e i dettagli di codifica.

const saveOpts = new GltfSaveOptions();

// Set to true for a single binary .glb file
// Set to false (default) for JSON .gltf + separate .bin
saveOpts.binaryMode = true;

Opzioni aggiuntive che puoi impostare:

ProprietàTipoPredefinitoEffetto
binaryModebooleanfalsetrue → GLB, false → glTF JSON
flipTexCoordVbooleantrueCapovolgi l’asse UV verticale per la compatibilità del motore

Passo 5: Salva usando scene.save()

Passa il percorso di output, il descrittore GltfFormat e le opzioni configurate:

import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';

const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());

const saveOpts = new GltfSaveOptions();
saveOpts.binaryMode = true;   // produce .glb

scene.save('output.glb', GltfFormat.getInstance(), saveOpts);
console.log('Converted to GLB successfully');

Per produrre invece un file JSON .gltf:

saveOpts.binaryMode = false;
scene.save('output.gltf', GltfFormat.getInstance(), saveOpts);
console.log('Exported to glTF JSON successfully');

Passo 6: Verifica il file di output

Verifica che il file di output esista e abbia una dimensione diversa da zero:

import * as fs from 'fs';

const outputPath = 'output.glb';
const stats = fs.statSync(outputPath);
console.log(`Output file size: ${stats.size} bytes`);

if (stats.size === 0) {
    throw new Error('Export produced an empty file: check scene content');
}

Per una verifica round‑trip, ricarica il GLB e controlla il conteggio dei nodi:

import { Scene } from '@aspose/3d';
import { GltfLoadOptions } from '@aspose/3d/formats/gltf';

const verify = new Scene();
verify.open('output.glb', new GltfLoadOptions());

let nodeCount = 0;
function countNodes(node: any): void {
    nodeCount++;
    for (const child of node.childNodes) countNodes(child);
}
countNodes(verify.rootNode);

console.log(`Round-trip verification: ${nodeCount} node(s) in output`);

Problemi comuni e soluzioni

File materiale OBJ non trovato dopo l’esportazione
Quando si salva in OBJ tramite scene.save('output.obj'), il file materiale .mtl viene scritto accanto al file .obj automaticamente. Assicurarsi che la directory di output sia scrivibile e che entrambi i file siano mantenuti insieme.

L’output .glb è più piccolo del previsto / le mesh mancano
Se la scena caricata contiene nodi senza entità (ad es., gruppi vuoti da un OBJ), il GLB non conterrà la geometria di tali nodi. Verifica che il tuo file di input abbia dati poligonali effettivi usando mesh.controlPoints.length > 0 prima di salvare.

Impossibile trovare il modulo ‘@aspose/3d/formats/gltf’ Assicurati di essere su Node.js 18+ e che @aspose/3d sia installato nella stessa node_modules del tuo punto di ingresso. Esegui npm ls @aspose/3d per confermare che la versione sia 24.12.0 o successiva.

GltfFormat.getInstance() restituisce undefined
Questo indica una discrepanza di versione tra il pacchetto principale @aspose/3d e una versione più vecchia nella cache. Elimina node_modules e package-lock.json, quindi esegui nuovamente npm install.

Le texture mancano nel GLB di output
Assicurati che binaryMode = true sia impostato per produrre un GLB autonomo. Per l’output JSON glTF, i file immagine delle texture devono essere presenti accanto al file di output poiché sono referenziati tramite percorso relativo.

Errore di tipo: Argomento di tipo ‘GltfSaveOptions’ non assegnabile
Assicurati che sia Scene sia GltfSaveOptions siano importati dalla stessa istanza del pacchetto installato. Le installazioni miste (globali + locali) possono causare incompatibilità di interfaccia.

Domande Frequenti (FAQ)

Qual è la differenza tra glTF e GLB?
glTF 2.0 JSON (.gltf) memorizza il grafo della scena come un file JSON leggibile dall’uomo con buffer .bin separati e file immagine. GLB (.glb) incapsula tutto in un unico contenitore binario. Imposta binaryMode = true per GLB, false per JSON glTF.

Posso esportare una scena costruita interamente in codice (senza file sorgente)?
Sì. Crea un Scene, aggiungi oggetti Node, collega Mesh o altre entità, quindi chiama scene.save(). La scena non deve necessariamente originarsi da un file caricato.

L’esportazione glTF è senza perdita?
Per la geometria e le trasformazioni, sì. I materiali sono mappati alle proprietà dei materiali PBR di glTF dove possibile. Le estensioni proprietarie dei materiali FBX potrebbero non effettuare un round‑trip perfetto.

Posso esportare in STL o 3MF invece?
Sì. Il modello è identico; importa i corrispondenti *SaveOptions e *Format.getInstance():

import { StlSaveOptions, StlFormat } from '@aspose/3d/formats/stl';
const opts = new StlSaveOptions();
scene.save('output.stl', StlFormat.getInstance(), opts);

scene.save() viene eseguito in modo asincrono?
No. scene.save() è sincrono. Avvolgilo in un thread di lavoro se devi evitare di bloccare il ciclo di eventi durante esportazioni di grandi dimensioni.

Quali versioni di Node.js sono supportate? Node.js 18, 20 e 22+. Node.js 16 e versioni precedenti non sono supportate.

Vedi anche

 Italiano