Cómo cargar modelos 3D en TypeScript
El @aspose/3d El paquete brinda a las aplicaciones TypeScript y Node.js una API sencilla para abrir archivos de escena 3D. Scene es el objeto raíz: llame a scene.open() con una ruta de archivo y opciones de carga específicas del formato opcionales, luego recorra scene.rootNode para acceder a la geometría, los materiales y las transformaciones.
Guía paso a paso
Paso 1: Instalar @aspose/3d vía npm
Agregue el paquete a su proyecto. No se requieren binarios nativos ni herramientas de compilación específicas de la plataforma; solo Node.js 18 o posterior.
npm install @aspose/3dPara proyectos TypeScript, las definiciones de tipos se incluyen con el paquete:
##tsconfig.json: minimum required settings
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true
}
}Paso 2: Importar Scene y opciones específicas del formato
Cada formato expone su propia clase cargadora y objeto de opciones bajo una subruta. Importe solo lo que necesite:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';Para otros formatos el patrón es idéntico:
import { GltfLoadOptions } from '@aspose/3d/formats/gltf';
import { FbxLoadOptions } from '@aspose/3d/formats/fbx';
import { StlLoadOptions } from '@aspose/3d/formats/stl';Paso 3: Abrir un archivo 3D usando scene.open()
Cree un Scene instancia, luego llame a scene.open() con la ruta del archivo y un objeto de opciones de carga opcional. La llamada es sincrónica.
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');Para cargar desde un Buffer ya en memoria (útil en contextos sin servidor o de transmisión):
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());Paso 4: Iterar sobre los nodos de la escena
El grafo de escena es un árbol enraizado en scene.rootNode. Cada Node puede contener nodos hijos y un opcional entity (malla, cámara, luz, etc.).
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);Paso 5: Acceder a los datos de vértices de la malla mediante controlPoints
Cuando la entidad de un nodo es una Mesh, puedes leer los puntos de control sin procesar (vértices) del controlPoints array. Cada entrada es una Vector4 con x, y, z, y w componentes.
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)}`);
}
}
}Paso 6: Configurar ObjLoadOptions para la carga de materiales
ObjLoadOptions expone propiedades para controlar cómo los .mtl archivos de material y texturas se resuelven.
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}`);
}
}Problemas comunes y soluciones
Error: No se puede encontrar el módulo ‘@aspose/3d/formats/obj’ Las subrutas de formato requieren exportaciones de paquetes de Node.js 12.7+. Asegúrate de estar en Node.js 18 o posterior. Si usas TypeScript, establece "moduleResolution": "node16" o "bundler" en tsconfig.json.
scene.rootNode.childNodes está vacío después de open() Algunos archivos OBJ usan terminaciones de línea no estándar o carecen de una nueva línea final. Verifica que el archivo sea un OBJ válido abriéndolo en un editor de texto. También confirma que hayas pasado ObjLoadOptions y no un genérico LoadOptions: las opciones específicas del formato son necesarias para una distribución correcta.
La matriz controlPoints tiene longitud cero Es posible que la malla se haya cargado pero no contenga geometría (p. ej., un grupo vacío en el OBJ). Usa mesh.polygonCount para comprobar antes de iterar los vértices.
El uso de memoria es alto para archivos grandes Cargar-desde-búfer con scene.openFromBuffer() no reduce la memoria máxima: el archivo completo debe ser analizado. Para archivos grandes (> 100 MB), asegúrate de que tu proceso Node.js tenga suficiente heap: node --max-old-space-size=4096 yourScript.js.
Errores de tipo: ’entity’ es de tipo ‘unknown’ El entity propiedad está tipada de forma amplia. Convierte a any o a una clase específica (Mesh, Camera, etc.) dependiendo de lo que esperes en tu escena.
Preguntas frecuentes (FAQ)
¿Qué formatos se pueden cargar con scene.open()? OBJ, glTF 2.0 (.gltf + .bin), GLB, STL, 3MF, FBX y COLLADA (.dae) son todos compatibles para importación. Pasa la *LoadOptions clase correspondiente a cada formato.
¿Puedo cargar un archivo sin especificar opciones? Sí. scene.open('model.glb') funciona sin opciones para formatos que no requieren configuración especial. Pasar opciones se recomienda para OBJ porque la resolución del material depende de enableMaterials.
¿La carga se ejecuta de forma asíncrona? No. scene.open() y scene.openFromBuffer() son síncronas. Envuélvalas en un hilo de trabajo o setImmediate si necesitas mantener un bucle de eventos receptivo.
¿Se admite la exportación OBJ? Sí. La exportación OBJ es compatible a través de scene.save('output.obj'). El .mtl el archivo de material se escribe automáticamente junto al .obj archivo.
¿Dónde se espera el archivo .mtl al cargar un OBJ? Por defecto, el analizador busca el .mtl archivo referenciado dentro del OBJ (mtllib directiva) relativo al directorio del archivo OBJ. Asegúrate de que ambos archivos estén en la misma carpeta.