Come caricare modelli 3D in TypeScript
Il @aspose/3d Il pacchetto fornisce alle applicazioni TypeScript e Node.js un’API semplice per aprire file di scene 3D. Scene è l’oggetto radice: chiama scene.open() con un percorso file e opzioni di caricamento opzionali specifiche del formato, quindi attraversa scene.rootNode per accedere a geometria, materiali e trasformazioni.
Guida passo-passo
Passo 1: Installa @aspose/3d tramite npm
Aggiungi il pacchetto al tuo progetto. Non sono richiesti binari nativi o strumenti di compilazione specifici per la piattaforma; è sufficiente Node.js 18 o successivo.
npm install @aspose/3dPer i progetti TypeScript, le definizioni dei tipi sono incluse nel pacchetto:
##tsconfig.json: minimum required settings
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true
}
}Passo 2: Importa Scene e le opzioni specifiche del formato
Ogni formato espone la propria classe loader e l’oggetto delle opzioni in un sotto‑percorso. Importa solo ciò di cui hai bisogno:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';Per gli altri formati il modello è identico:
import { GltfLoadOptions } from '@aspose/3d/formats/gltf';
import { FbxLoadOptions } from '@aspose/3d/formats/fbx';
import { StlLoadOptions } from '@aspose/3d/formats/stl';Passo 3: Apri un file 3D usando scene.open()
Crea un Scene istanza, quindi chiama scene.open() con il percorso del file e un oggetto di opzioni di caricamento opzionale. La chiamata è sincrona.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const scene = new Scene();
const options = new ObjLoadOptions();
options.enableMaterials = true;
scene.open('model.obj', options);
console.log('Scene loaded successfully');Per caricare da un Buffer già in memoria (utile in contesti serverless o di streaming):
import * as fs from 'fs';
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const buffer = fs.readFileSync('model.obj');
const scene = new Scene();
scene.openFromBuffer(buffer, new ObjLoadOptions());Passo 4: Itera sui nodi della scena
Il grafo della scena è un albero radicato in scene.rootNode. Node Ogni entity può contenere nodi figli e un opzionale.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());
function visitNode(node: any, depth: number = 0): void {
const indent = ' '.repeat(depth);
console.log(`${indent}Node: ${node.name}`);
if (node.entity) {
console.log(`${indent} Entity type: ${node.entity.constructor.name}`);
}
for (const child of node.childNodes) {
visitNode(child, depth + 1);
}
}
visitNode(scene.rootNode);Passo 5: Accedi ai dati dei vertici della mesh tramite controlPoints
Quando l’entità di un nodo è un Mesh, è possibile leggere i punti di controllo grezzi (vertici) dal controlPoints array. Ogni voce è un Vector4 con x, y, z, e w componenti.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());
for (const node of scene.rootNode.childNodes) {
if (!node.entity) continue;
const entity = node.entity;
// Check if the entity is a Mesh by duck-typing controlPoints
if ('controlPoints' in entity) {
const mesh = entity as any;
console.log(`Mesh "${node.name}": ${mesh.controlPoints.length} vertices`);
// Print first three vertices
for (let i = 0; i < Math.min(3, mesh.controlPoints.length); i++) {
const v = mesh.controlPoints[i];
console.log(` v[${i}]: x=${v.x.toFixed(4)}, y=${v.y.toFixed(4)}, z=${v.z.toFixed(4)}`);
}
}
}Passo 6: Configura ObjLoadOptions per il caricamento dei materiali
ObjLoadOptions espone proprietà per controllare come i file .mtl di materiale e le texture vengono risolti.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const options = new ObjLoadOptions();
options.enableMaterials = true; // parse .mtl file if present
const scene = new Scene();
scene.open('model.obj', options);
// Inspect materials attached to nodes
for (const node of scene.rootNode.childNodes) {
if (node.material) {
console.log(`Material on "${node.name}": ${node.material.constructor.name}`);
}
}Problemi comuni e soluzioni
Errore: Impossibile trovare il modulo ‘@aspose/3d/formats/obj’ I sotto‑percorsi del formato richiedono le esportazioni dei pacchetti di Node.js 12.7+. Assicurati di utilizzare Node.js 18 o successivo. Se usi TypeScript, imposta "moduleResolution": "node16" oppure "bundler" in tsconfig.json.
scene.rootNode.childNodes è vuoto dopo open() Alcuni file OBJ usano terminazioni di riga non standard o mancano di una nuova riga finale. Verifica che il file sia un OBJ valido aprendolo in un editor di testo. Conferma inoltre di aver passato ObjLoadOptions e non un generico LoadOptions: le opzioni specifiche del formato sono necessarie per una corretta distribuzione.
l’array controlPoints ha lunghezza zero La mesh potrebbe essere stata caricata ma non contiene geometria (ad es., un gruppo vuoto nell’OBJ). Usa mesh.polygonCount per verificare prima di iterare i vertici.
L’utilizzo della memoria è elevato per file di grandi dimensioni Caricamento da buffer con scene.openFromBuffer() non riduce la memoria di picco: l’intero file deve essere analizzato. Per file di grandi dimensioni (> 100 MB), assicurati che il tuo processo Node.js disponga di heap sufficiente: node --max-old-space-size=4096 yourScript.js.
Errori di tipo: ’entity’ è di tipo ‘unknown’ Il entity la proprietà è tipizzata in modo generico. Cast a any o a una classe specifica (Mesh, Camera, ecc.) a seconda di ciò che ti aspetti nella tua scena.
Domande frequenti (FAQ)
Quali formati possono essere caricati con scene.open()? OBJ, glTF 2.0 (.gltf + .bin), GLB, STL, 3MF, FBX e COLLADA (.dae) sono tutti supportati per l’importazione. Passa la classe corrispondente *LoadOptions per ogni formato.
Posso caricare un file senza specificare opzioni? Sì. scene.open('model.glb') funziona senza opzioni per i formati che non richiedono configurazioni speciali. È consigliato passare le opzioni per OBJ perché la risoluzione dei materiali dipende da enableMaterials.
Il caricamento avviene in modo asincrono? No. scene.open() e scene.openFromBuffer() sono sincroni. Avvolgili in un thread di lavoro o setImmediate se hai bisogno di mantenere reattivo un ciclo di eventi.
L’esportazione OBJ è supportata? Sì. L’esportazione OBJ è supportata tramite scene.save('output.obj'). Il .mtl file dei materiali viene scritto automaticamente accanto al .obj file.
Dove ci si aspetta il file .mtl durante il caricamento di OBJ? Per impostazione predefinita, il parser cerca il .mtl file referenziato all’interno dell’OBJ (mtllib directive) relativo alla directory del file OBJ. Assicurati che entrambi i file siano nella stessa cartella.