Cómo exportar escenas 3D a glTF/GLB en TypeScript

Cómo exportar escenas 3D a glTF/GLB en TypeScript

Aspose.3D FOSS admite glTF 2.0 tanto como formato de importación como de exportación. El mismo objeto Scene puede poblarse a partir de un archivo OBJ, FBX, STL u otro archivo fuente y luego escribirse en .gltf (JSON + binario externo) o .glb (contenedor binario único) estableciendo una bandera en GltfSaveOptions.

Guía paso a paso

Paso 1: Instalar @aspose/3d

npm install @aspose/3d

Confirme que Node.js 18 o posterior está activo:

node --version   # must be >= 16.0.0

Paso 2: Importar Scene, GltfSaveOptions y GltfFormat

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

GltfFormat es el descriptor de formato pasado a scene.save(). GltfSaveOptions lleva toda la configuración de exportación.

Si también está cargando un archivo fuente (p. ej., OBJ), importe las opciones de carga correspondientes:

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

Paso 3: Construir o cargar una escena

Opción A: Cargar desde un archivo existente (conversión 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());

Opción B: Construir una escena mínima programáticamente:

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

Paso 4: Configurar GltfSaveOptions

GltfSaveOptions controla el formato de salida y los detalles de codificación.

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;

Opciones adicionales que puede establecer:

PropiedadTipoPredeterminadoEfecto
binaryModebooleanfalsetrue → GLB, false → glTF JSON
flipTexCoordVbooleantrueVoltear el eje UV vertical para compatibilidad del motor

Paso 5: Guardar usando scene.save()

Pase la ruta de salida, el descriptor GltfFormat y las opciones configuradas:

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');

Para producir un archivo JSON .gltf en su lugar:

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

Paso 6: Verificar el archivo de salida

Verifique que el archivo de salida exista y tenga un tamaño distinto de cero:

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');
}

Para una verificación de ida y vuelta, vuelva a cargar el GLB y examine el recuento de nodos:

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`);

Problemas comunes y soluciones

Archivo de material OBJ no encontrado después de la exportación
Al guardar a OBJ mediante scene.save('output.obj'), el archivo de material .mtl se escribe junto al archivo .obj automáticamente. Asegúrese de que el directorio de salida sea escribible y de que ambos archivos se mantengan juntos.

Salida .glb es más pequeña de lo esperado / faltan mallas
Si la escena cargada tiene nodos sin entidades (p. ej., grupos vacíos de un OBJ), el GLB no contendrá la geometría de esos nodos. Confirme que su archivo de entrada tiene datos de polígonos reales usando mesh.controlPoints.length > 0 antes de guardar.

No se puede encontrar el módulo ‘@aspose/3d/formats/gltf’ Asegúrese de estar en Node.js 18+ y de que @aspose/3d esté instalado en el mismo node_modules que su punto de entrada. Ejecute npm ls @aspose/3d para confirmar que la versión es 24.12.0 o posterior.

GltfFormat.getInstance() devuelve undefined
Esto indica una incompatibilidad de versiones entre el paquete principal @aspose/3d y una versión anterior en caché. Elimine node_modules y package-lock.json, luego ejecute npm install nuevamente.

Faltan texturas en el GLB de salida
Asegúrese de que binaryMode = true esté configurado para producir un GLB autocontenido. Para la salida JSON de glTF, los archivos de imagen de textura deben estar presentes junto al archivo de salida, ya que se hacen referencia mediante una ruta relativa.

Error de tipo: El argumento de tipo ‘GltfSaveOptions’ no es asignable
Asegúrese de que tanto Scene como GltfSaveOptions se importen desde la misma instancia del paquete instalado. Las instalaciones mixtas (global + local) pueden causar incompatibilidades de interfaz.

Preguntas Frecuentes (FAQ)

¿Cuál es la diferencia entre glTF y GLB?
glTF 2.0 JSON (.gltf) almacena el grafo de escena como un archivo JSON legible por humanos con buffers .bin separados y archivos de imagen. GLB (.glb) empaqueta todo en un único contenedor binario. Establezca binaryMode = true para GLB, false para JSON glTF.

¿Puedo exportar una escena que se construyó completamente en código (sin archivo fuente)?
Sí. Cree un Scene, añada objetos Node, adjunte Mesh u otras entidades, y luego llame a scene.save(). La escena no necesita originarse a partir de un archivo cargado.

¿La exportación glTF es sin pérdida?
Para geometría y transformaciones, sí. Los materiales se asignan a las propiedades de material PBR de glTF donde sea posible. Las extensiones de material propietarias de FBX pueden no hacer un round‑trip perfectamente.

¿Puedo exportar a STL o 3MF en su lugar?
Sí. El patrón es idéntico; importe los *SaveOptions y *Format.getInstance() del formato correspondiente:

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

¿Ejecuta scene.save() de forma asíncrona?
No. scene.save() es sincrónico. Envuélvelo en un hilo de trabajo si necesitas evitar bloquear el bucle de eventos durante exportaciones grandes.

¿Qué versiones de Node.js son compatibles? Node.js 18, 20 y 22+. Node.js 16 y versiones anteriores no son compatibles.

Ver también

 Español