Caratteristiche e funzionalità
Aspose.3D FOSS per TypeScript è una libreria Node.js rilasciata sotto licenza MIT per caricare, costruire ed esportare scene 3D. Viene fornita con definizioni di tipo TypeScript complete, una singola dipendenza runtime (xmldom), e supporto per sei principali formati di file 3D. Questa pagina è il riferimento principale per tutte le aree funzionali e include esempi di codice TypeScript eseguibili per ciascuna.
Installazione e configurazione
Installa il pacchetto da npm usando un unico comando:
npm install @aspose/3dIl pacchetto mira a CommonJS e richiede Node.js 18 o versioni successive. Dopo l’installazione, verifica il tuo tsconfig.json includono le seguenti opzioni del compilatore per una piena compatibilità:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true
}
}Importa il principale Scene classe dalla radice del pacchetto. Le classi di opzioni specifiche per formato vengono importate dai rispettivi sotto‑percorsi:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';Caratteristiche e funzionalità
Supporto dei formati
Aspose.3D FOSS per TypeScript legge e scrive sei principali formati di file 3D. Il rilevamento del formato è automatico tramite i numeri magici binari durante il caricamento, quindi non è necessario specificare esplicitamente il formato di origine.
| Formato | Leggi | Scrivi | Note |
|---|---|---|---|
| OBJ (Wavefront) | Sì | Sì | Legge/scrive .mtl materiali; usa ObjLoadOptions.enableMaterials per l’importazione |
| glTF 2.0 | Sì | Sì | Formato di testo JSON; materiali PBR |
| GLB | Sì | Sì | glTF binario; impostato GltfSaveOptions.binaryMode = true |
| STL | Sì | Sì | Binario e ASCII; roundtrip completo verificato |
| 3MF | Sì | Sì | 3D Manufacturing Format with color and material metadata |
| FBX | No* | No* | Importatore/esportatore esistono ma il rilevamento automatico del formato non è collegato |
| COLLADA (DAE) | Sì | Sì | Scalatura delle unità, geometria, materiali e clip di animazione |
Caricamento di OBJ con materiali:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const scene = new Scene();
const options = new ObjLoadOptions();
options.enableMaterials = true;
options.flipCoordinateSystem = false;
options.scale = 1.0;
options.normalizeNormal = true;
scene.open('model.obj', options);Salvataggio in GLB (glTF binario):
import { Scene } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
// ... build or load scene content
const opts = new GltfSaveOptions();
opts.binaryMode = true;
scene.save('output.glb', GltfFormat.getInstance(), opts);Scene Graph
Tutti i contenuti 3D sono organizzati come un albero di Node oggetti radicati in scene.rootNode. Ogni nodo può trasportare un Entity (un Mesh, Camera, Light, o altro SceneObject) e un Transform che lo posiziona rispetto al suo genitore.
Classi chiave del grafo della scena:
Scene: il contenitore di livello superiore; contienerootNodeeanimationClipsNode: un nodo ad albero denominato conchildNodes,entity,transform, ematerialsEntity: classe base per oggetti collegabili (Mesh,Camera,Light)SceneObject: classe base condivisa daNodeeEntityA3DObject: classe base radice connamee sacchetto di proprietàTransform: traslazione locale, rotazione (Euler e Quaternion) e scala
Attraversamento del grafo della scena:
import { Scene, Node, Mesh } from '@aspose/3d';
const scene = new Scene();
scene.open('model.obj');
function visit(node: Node, depth: number = 0): void {
const indent = ' '.repeat(depth);
console.log(`${indent}Node: ${node.name}`);
if (node.entity) {
console.log(`${indent} Entity: ${node.entity.constructor.name}`);
}
for (const child of node.childNodes) {
visit(child, depth + 1);
}
}
visit(scene.rootNode);Creare una gerarchia di scena programmaticamente:
import { Scene, Node } from '@aspose/3d';
const scene = new Scene();
const parent = scene.rootNode.createChildNode('chassis');
const wheel = parent.createChildNode('wheel_fl');
wheel.transform.translation.set(0.9, -0.3, 1.4);Geometria e Mesh
Mesh è il tipo di geometria principale. Estende Geometry e espone punti di controllo (vertici), indici dei poligoni e elementi dei vertici per normali, UV e colori dei vertici.
Classi chiave di geometria:
Mesh: mesh poligonale concontrolPointsepolygonCountGeometry: classe base con gestione degli elementi dei verticiVertexElementNormal: normali per vertice o per vertice di poligonoVertexElementUV: coordinate di texture (uno o più canali UV)VertexElementVertexColor: dati di colore per verticeMappingMode: controlla come i dati degli elementi vengono mappati sui poligoniCONTROL_POINT,POLYGON_VERTEX,POLYGON,EDGE,ALL_SAME)ReferenceMode:controlla la strategia di indicizzazione (DIRECT,INDEX,INDEX_TO_DIRECT)VertexElementType:identifica la semantica di un elemento verticeTextureMapping:enumerazione dei canali texture
Lettura dei dati mesh da una scena caricata:
import { Scene, Mesh, VertexElementType } from '@aspose/3d';
const scene = new Scene();
scene.open('model.stl');
for (const node of scene.rootNode.childNodes) {
if (node.entity instanceof Mesh) {
const mesh = node.entity as Mesh;
console.log(`Mesh "${node.name}": ${mesh.controlPoints.length} vertices, ${mesh.polygonCount} polygons`);
const normals = mesh.getElement(VertexElementType.NORMAL);
if (normals) {
console.log(` Normal mapping: ${normals.mappingMode}`);
}
}
}Sistema dei materiali
Aspose.3D FOSS per TypeScript supporta tre tipi di materiale che coprono l’intera gamma, dallo shading Phong legacy al rendering basato sulla fisica:
LambertMaterial:colore diffuso e colore ambientale; mappa a materiali OBJ/DAE sempliciPhongMaterial:aggiunge colore speculare, lucentezza e emissivo; il tipo di materiale OBJ predefinitoPbrMaterial:modello fisicamente basato di rugosità/metallicità; usato per l’importazione ed esportazione glTF 2.0
Lettura dei materiali da una scena OBJ caricata:
import { Scene, PhongMaterial, LambertMaterial } 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);
for (const node of scene.rootNode.childNodes) {
for (const mat of node.materials) {
if (mat instanceof PhongMaterial) {
const phong = mat as PhongMaterial;
console.log(` Phong: diffuse=${JSON.stringify(phong.diffuseColor)}, shininess=${phong.shininess}`);
} else if (mat instanceof LambertMaterial) {
console.log(` Lambert: diffuse=${JSON.stringify((mat as LambertMaterial).diffuseColor)}`);
}
}
}Applicazione di un materiale PBR durante la costruzione di una scena glTF:
import { Scene, Node, PbrMaterial } from '@aspose/3d';
import { Vector3 } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
const node = scene.rootNode.createChildNode('sphere');
const mat = new PbrMaterial();
mat.albedo = new Vector3(0.8, 0.2, 0.2); // red-tinted albedo; albedo starts null, must assign
mat.metallicFactor = 0.0;
mat.roughnessFactor = 0.5;
node.material = mat;
const opts = new GltfSaveOptions();
opts.binaryMode = false;
scene.save('output.gltf', GltfFormat.getInstance(), opts);Utility matematiche
La libreria include un set completo di tipi matematici 3D, tutti completamente tipizzati:
Vector3:vettore a 3 componenti; supportaminus(),times(),dot(),cross(),normalize(),length,angleBetween()Vector4:vettore a 4 componenti per coordinate omogeneeMatrix4:matrice di trasformazione 4×4 conconcatenate(),transpose,decompose,setTRSQuaternion:quaternione di rotazione confromEulerAngle()(statico, singolare),eulerAngles()(metodo di istanza),slerp(),normalize()BoundingBox:box di delimitazione allineato agli assi conminimum,maximum,center,size,mergeFVector3:variante a precisione singola diVector3usato nei dati degli elementi vertice
Calcolo di un bounding box dai vertici della mesh:
import { Scene, Mesh, Vector3, BoundingBox } from '@aspose/3d';
const scene = new Scene();
scene.open('model.obj');
let box = new BoundingBox();
for (const node of scene.rootNode.childNodes) {
if (node.entity instanceof Mesh) {
for (const pt of (node.entity as Mesh).controlPoints) {
box.merge(new Vector3(pt.x, pt.y, pt.z));
}
}
}
console.log('Center:', box.center);
console.log('Extents:', box.size);Costruzione di una trasformazione da angoli di Eulero:
import { Quaternion, Vector3, Matrix4 } from '@aspose/3d';
const rot = Quaternion.fromEulerAngle(0, Math.PI / 4, 0); // 45° around Y
const mat = new Matrix4();
mat.setTRS(new Vector3(0, 0, 0), rot, new Vector3(1, 1, 1));Sistema di animazione
L’API di animazione modella clip, nodi, canali e sequenze di fotogrammi chiave:
AnimationClip:collezione denominata di nodi di animazione; accessibile tramitescene.animationClips; esponeanimations: AnimationNode[]AnimationNode: gruppo denominato diBindPoints; creato tramiteclip.createAnimationNode(name), accessibile tramiteclip.animationsBindPoint: associa unAnimationNodea una proprietà specifica su un oggetto della scena; esponepropertyechannelsCountAnimationChannel: estendeKeyframeSequence; contiene un separatokeyframeSequence; accessibile tramitebindPoint.getChannel(name)KeyFrame: una singola coppia tempo/valore; trasporta per-keyframeinterpolation: InterpolationKeyframeSequence: elenco ordinato diKeyFrameoggetti tramitekeyFrames; hapreBehaviorepostBehavior(Extrapolation)Interpolation: enum:LINEAR,CONSTANT,BEZIER,B_SPLINE,CARDINAL_SPLINE,TCB_SPLINEExtrapolation: classe contype: ExtrapolationTypeerepeatCount: numberExtrapolationType: enum:CONSTANT,GRADIENT,CYCLE,CYCLE_RELATIVE,OSCILLATE
Lettura dei dati di animazione da una scena caricata:
import { Scene, AnimationNode, BindPoint } from '@aspose/3d';
const scene = new Scene();
scene.open('animated.dae'); // COLLADA animation import is supported
for (const clip of scene.animationClips) {
console.log(`Clip: "${clip.name}"`);
for (const animNode of clip.animations) { // clip.animations, not clip.nodes
console.log(` AnimationNode: ${animNode.name}`);
for (const bp of animNode.bindPoints) { // animNode.bindPoints, not animNode.channels
console.log(` BindPoint: property="${bp.property.name}", channels=${bp.channelsCount}`);
}
}
}Supporto per Stream e Buffer
Usa scene.openFromBuffer() per caricare una scena 3D direttamente da una memoria in-memory Buffer. Questo è lo schema consigliato per le funzioni serverless, le pipeline di streaming e l’elaborazione di risorse recuperate via HTTP senza scrivere su disco.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import * as fs from 'fs';
// Load file into memory, then parse from buffer
const buffer: Buffer = fs.readFileSync('model.obj');
const scene = new Scene();
const options = new ObjLoadOptions();
options.enableMaterials = true;
scene.openFromBuffer(buffer, options);
for (const node of scene.rootNode.childNodes) {
if (node.entity) {
console.log(node.name, node.entity.constructor.name);
}
}Il rilevamento automatico del formato tramite i numeri magici binari si applica durante il caricamento da buffer, quindi i file GLB, STL binari e 3MF vengono riconosciuti senza dover specificare un parametro di formato.
Esempi di utilizzo
Esempio 1: Carica OBJ ed esporta in GLB
Questo esempio carica un file Wavefront OBJ con i materiali, quindi riesporta la scena come file glTF binario (GLB) adatto per l’uso sul web e nei motori di gioco.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
function convertObjToGlb(inputPath: string, outputPath: string): void {
const scene = new Scene();
const loadOpts = new ObjLoadOptions();
loadOpts.enableMaterials = true;
loadOpts.flipCoordinateSystem = false;
loadOpts.normalizeNormal = true;
scene.open(inputPath, loadOpts);
// Report what was loaded
for (const node of scene.rootNode.childNodes) {
if (node.entity) {
console.log(`Loaded: ${node.name} (${node.entity.constructor.name})`);
}
}
const saveOpts = new GltfSaveOptions();
saveOpts.binaryMode = true; // write .glb instead of .gltf + .bin
scene.save(outputPath, GltfFormat.getInstance(), saveOpts);
console.log(`Exported GLB to: ${outputPath}`);
}
convertObjToGlb('input.obj', 'output.glb');Esempio 2: Round-Trip STL con convalida delle normali
Questo esempio carica un file STL binario, stampa le informazioni delle normali per vertice, quindi riesporta la scena come STL ASCII e verifica il round‑trip.
import { Scene, Mesh, VertexElementNormal, VertexElementType } from '@aspose/3d';
import { StlLoadOptions, StlSaveOptions } from '@aspose/3d/formats/stl';
const scene = new Scene();
const loadOpts = new StlLoadOptions();
scene.open('model.stl', loadOpts);
let totalPolygons = 0;
for (const node of scene.rootNode.childNodes) {
if (node.entity instanceof Mesh) {
const mesh = node.entity as Mesh;
totalPolygons += mesh.polygonCount;
const normElem = mesh.getElement(VertexElementType.NORMAL) as VertexElementNormal | null;
if (normElem) {
console.log(` Normals: ${normElem.data.length} entries, mapping=${normElem.mappingMode}`);
}
}
}
console.log(`Total polygons: ${totalPolygons}`);
// Re-export as ASCII STL
const saveOpts = new StlSaveOptions();
saveOpts.binaryMode = false; // ASCII output
scene.save('output_ascii.stl', saveOpts);Esempio 3: Costruire una scena programmaticamente e salvarla come glTF
Questo esempio costruisce una scena con un materiale PBR da zero e la salva come file JSON glTF.
import { Scene, Mesh, PbrMaterial, Vector4, Vector3 } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
const node = scene.rootNode.createChildNode('floor');
// Build a simple quad mesh (two triangles)
// controlPoints are Vector4 (x, y, z, w) where w=1 for positions
const mesh = new Mesh();
mesh.controlPoints.push(
new Vector4(-1, 0, -1, 1),
new Vector4( 1, 0, -1, 1),
new Vector4( 1, 0, 1, 1),
new Vector4(-1, 0, 1, 1),
);
mesh.createPolygon([0, 1, 2]);
mesh.createPolygon([0, 2, 3]);
node.entity = mesh;
// Apply a PBR material
const mat = new PbrMaterial();
mat.albedo = new Vector3(0.6, 0.6, 0.6); // albedo starts null, must assign
mat.metallicFactor = 0.0;
mat.roughnessFactor = 0.8;
node.material = mat;
// Save as JSON glTF
const opts = new GltfSaveOptions();
opts.binaryMode = false;
scene.save('floor.gltf', GltfFormat.getInstance(), opts);
console.log('Scene written to floor.gltf');Suggerimenti e migliori pratiche
- Usa
ObjLoadOptions.enableMaterials = trueogni volta che hai bisogno dei dati dei materiali dai file .mtl. Senza di esso, l’elenco dei materiali su ogni nodo sarà vuoto. - Preferisci
binaryMode = trueper GLB quando si producono asset per il web o per motori di gioco. Il GLB binario è un unico file autonomo e si carica più velocemente nei browser e nei motori rispetto alla divisione JSON + .bin. - Usa
openFromBuffer()in ambienti serverless per evitare I/O di file temporanei. Recupera l’asset, passa ilBufferdirettamente, e scrivi l’output su uno stream o su un altro buffer. - Verifica
node.entityprima del casting: non tutti i nodi contengono un’entità. Proteggi sempre con uninstanceofcontrollo prima di accedereMesh-specifiche proprietà comecontrolPoints. - Imposta
normalizeNormal = trueinObjLoadOptionsquando i tuoi file OBJ di origine provengono da fonti non attendibili. Questo impedisce che normali degeneri si propaghino nei passaggi di rendering o di validazione a valle. - Mantieni
strict: truein tsconfig.json: la libreria è stata creata connoImplicitAnyestrictNullChecks. Disabilitandostrictnasconde i veri errori di tipo e nega il valore dell’API tipizzata. - Attraversa tramite
childNodes, non un ciclo di indice: ilchildNodesla proprietà restituisce un iterabile; evita di fare affidamento sull’indicizzazione numerica per la compatibilità futura.
Problemi comuni
| Sintomo | Causa probabile | Correzione |
|---|---|---|
| Elenco dei materiali vuoto dopo il caricamento OBJ | enableMaterials non impostato | Imposta options.enableMaterials = true |
| Il file GLB contiene un file .bin separato | binaryMode impostazione predefinita su false | Imposta opts.binaryMode = true |
| Normali dei vertici mancanti nell’output STL | La modalità STL ASCII omette le normali per faccia | Passa a binaryMode = true oppure calcola le normali prima dell’esportazione |
node.entity è sempre null | Solo attraversando rootNode, non i suoi figli | Ricorsione in node.childNodes |
| Errore TypeScript: la proprietà non esiste | Vecchio @types cache | Esegui npm install @aspose/3d di nuovo; nessun separato @types pacchetto è necessario |
openFromBuffer genera errore di formato | Formato non rilevabile automaticamente dal magic | Passa la classe di opzione di formato esplicita come secondo argomento |
Domande frequenti
La libreria richiede addon nativi o pacchetti di sistema? No. Aspose.3D FOSS per TypeScript ha una singola dipendenza runtime: xmldom, che è puro JavaScript e viene installato automaticamente da npm. Non ci sono .node addon nativi e nessun pacchetto di sistema da installare.
Quali versioni di Node.js sono supportate? Node.js 18, 20 e 22 LTS. La libreria genera output CommonJS e utilizza funzionalità del linguaggio ES2020 internamente.
Posso usare la libreria in un bundle per browser (webpack/esbuild)? La libreria è destinata a Node.js e utilizza Node.js fs e Buffer API. Il bundling per browser non è ufficialmente supportato. Per l’uso in browser, carica la scena sul server e trasmetti il risultato (ad es., come GLB) al client.
Qual è la differenza tra GltfSaveOptions.binaryMode = true e false? binaryMode = false produce un .gltf file JSON più un separato .bin sidecar di buffer binario. binaryMode = true produce un unico file autonomo .glb file. Usa true per la consegna di asset in produzione.
Posso caricare un file da una risposta HTTP senza salvarlo su disco? Sì. Recupera la risposta come un Buffer (ad es., usando node-fetch o il built-in fetch in Node 18+), quindi chiama scene.openFromBuffer(buffer, options).
Il supporto FBX è completo? No. Le classi di importazione ed esportazione FBX esistono nella libreria, ma FBX non è integrato in Scene.open() oppure Scene.save() rilevamento automatico. Chiamare scene.open('file.fbx') non invocherà l’importatore FBX; il file verrà gestito dal percorso di fallback STL. Usa direttamente le classi importatore/esportatore specifiche per FBX se hai bisogno di I/O FBX. Vedi la tabella di supporto dei formati sopra, che indica FBX come No*.
La libreria supporta TypeScript 4.x? Si consiglia TypeScript 5.0+. TypeScript 4.7+ dovrebbe funzionare in pratica, ma la libreria è testata e sviluppata contro 5.0+.
Sommario del Riferimento API
| Classe | Modulo | Scopo |
|---|---|---|
Scene | @aspose/3d | Contenitore della scena di livello superiore; open(), openFromBuffer(), save(), rootNode, animationClips |
Node | @aspose/3d | Nodo del grafo della scena; childNodes, entity, transform, materials, createChildNode() |
Entity | @aspose/3d | Classe base per oggetti collegabili alla scena |
SceneObject | @aspose/3d | Classe base condivisa da Node e Entity |
A3DObject | @aspose/3d | Base radice con name e contenitore di proprietà |
Transform | @aspose/3d | Traslazione, rotazione e scala locali |
Mesh | @aspose/3d | Mesh poligonale; controlPoints, polygonCount, createPolygon(), elementi dei vertici |
Geometry | @aspose/3d | Classe base per tipi di geometria |
Camera | @aspose/3d | Entità fotocamera con campo visivo e impostazioni di proiezione |
Light | @aspose/3d | Entità luminosa (puntiforme, direzionale, spot) |
LambertMaterial | @aspose/3d | Modello di shading diffuso + ambientale |
PhongMaterial | @aspose/3d | Phong shading con speculare ed emissivo |
PbrMaterial | @aspose/3d | Modello basato sulla fisica di roughness/metallic per glTF |
Vector3 | @aspose/3d | 3-component double-precision vector |
Vector4 | @aspose/3d | 4-component vector for homogeneous math |
Matrix4 | @aspose/3d | 4×4 transformation matrix |
Quaternion | @aspose/3d | Quaternione di rotazione |
BoundingBox | @aspose/3d | Bounding box allineata agli assi |
FVector3 | @aspose/3d | Variante a precisione singola di Vector3 |
VertexElementNormal | @aspose/3d | Normali per vertice o per vertice di poligono |
VertexElementUV | @aspose/3d | Elemento vertice di coordinate texture |
VertexElementVertexColor | @aspose/3d | Elemento vertice di colore per vertice |
MappingMode | @aspose/3d | Enum: CONTROL_POINT, POLYGON_VERTEX, POLYGON, ALL_SAME |
ReferenceMode | @aspose/3d | Enum: DIRECT, INDEX, INDEX_TO_DIRECT |
AnimationClip | @aspose/3d | Animazione nominata; espone animations: AnimationNode[]; creata tramite scene.createAnimationClip(name) |
AnimationNode | @aspose/3d | Gruppo nominato di BindPoints; creata tramite clip.createAnimationNode(name) |
BindPoint | @aspose/3d | Associa un AnimationNode a una proprietà di oggetto scena; espone property e channelsCount |
AnimationChannel | @aspose/3d | Estende KeyframeSequence; contiene un keyframeSequence; accesso tramite bindPoint.getChannel(name) |
KeyFrame | @aspose/3d | Singola coppia di fotogrammi chiave tempo/valore; trasporta interpolation: Interpolation |
KeyframeSequence | @aspose/3d | Ordinato keyFrames elenco; preBehavior/postBehavior sono Extrapolation oggetti |
Interpolation | @aspose/3d | Enum: LINEAR, CONSTANT, BEZIER, B_SPLINE, CARDINAL_SPLINE, TCB_SPLINE |
Extrapolation | @aspose/3d | Classe con type: ExtrapolationType e repeatCount: number |
ExtrapolationType | @aspose/3d | Enum: CONSTANT, GRADIENT, CYCLE, CYCLE_RELATIVE, OSCILLATE |
ObjLoadOptions | @aspose/3d/formats/obj | Opzioni di importazione OBJ: enableMaterials, flipCoordinateSystem, scale, normalizeNormal |
GltfSaveOptions | @aspose/3d/formats/gltf | Opzioni di esportazione glTF/GLB: binaryMode |
GltfFormat | @aspose/3d/formats/gltf | Istanza di formato per glTF/GLB; passa a scene.save() |
StlLoadOptions | @aspose/3d/formats/stl | Opzioni di importazione STL |
StlSaveOptions | @aspose/3d/formats/stl | Opzioni di esportazione STL: binaryMode |
StlImporter | @aspose/3d/formats/stl | Lettore STL a basso livello |
StlExporter | @aspose/3d/formats/stl | Scrittore STL a basso livello |