Como carregar modelos 3D em TypeScript

Como carregar modelos 3D em TypeScript

O @aspose/3d o pacote fornece às aplicações TypeScript e Node.js uma API simples para abrir arquivos de cena 3D. Scene é o objeto raiz: chame scene.open() com um caminho de arquivo e opções de carregamento específicas de formato opcionais, então percorra scene.rootNode para acessar geometria, materiais e transformações.

Guia passo a passo

Etapa 1: Instale @aspose/3d via npm

Adicione o pacote ao seu projeto. Nenhum binário nativo ou ferramentas de compilação específicas de plataforma são necessárias; apenas Node.js 18 ou superior.

npm install @aspose/3d

Para projetos TypeScript, as definições de tipo são incluídas no pacote:

##tsconfig.json: minimum required settings
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true
  }
}

Etapa 2: Importe Scene e opções específicas de formato

Cada formato expõe sua própria classe de carregador e objeto de opções em um subcaminho. Importe apenas o que você precisa:

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

Para outros formatos o padrão é idêntico:

import { GltfLoadOptions } from '@aspose/3d/formats/gltf';
import { FbxLoadOptions } from '@aspose/3d/formats/fbx';
import { StlLoadOptions } from '@aspose/3d/formats/stl';

Etapa 3: Abra um arquivo 3D usando scene.open()

Crie um Scene instância, então chame scene.open() com o caminho do arquivo e um objeto de opções de carregamento opcional. A chamada é síncrona.

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 carregar de um Buffer já na memória (útil em contextos serverless ou de 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());

Etapa 4: Itere sobre os nós da cena

O grafo de cena é uma árvore enraizada em scene.rootNode. Cada Node pode conter nós filhos e um opcional entity (malha, câmera, 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);

Etapa 5: Acesse os dados de vértices da malha via controlPoints

Quando a entidade de um nó é um Mesh, você pode ler os pontos de controle brutos (vértices) a partir do controlPoints array. Cada entrada é um Vector4 com x, y, z, e 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)}`);
        }
    }
}

Etapa 6: Configure ObjLoadOptions para carregamento de materiais

ObjLoadOptions expõe propriedades para controlar como os arquivos .mtl de material e texturas são resolvidos.

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.entity && node.entity.material) {
        console.log(`Material on "${node.name}": ${node.entity.material.constructor.name}`);
    }
}

Problemas comuns e correções

Erro: Não foi possível encontrar o módulo ‘@aspose/3d/formats/obj’ Os subcaminhos de formato exigem exportações de pacote do Node.js 12.7+. Certifique-se de que está usando o Node.js 18 ou posterior. Se estiver usando TypeScript, defina "moduleResolution": "node16" ou "bundler" em tsconfig.json.

scene.rootNode.childNodes está vazio após open() Alguns arquivos OBJ usam quebras de linha não padrão ou não têm uma nova linha final. Verifique se o arquivo é um OBJ válido abrindo-o em um editor de texto. Também confirme se você passou ObjLoadOptions e não um genérico LoadOptions: as opções específicas do formato são necessárias para o despacho correto.

o array controlPoints tem comprimento zero A malha pode ter sido carregada, mas não contém geometria (por exemplo, um grupo vazio no OBJ). Use mesh.polygonCount para verificar antes de iterar vértices.

O uso de memória é alto para arquivos grandes Carregar a partir do buffer com scene.openFromBuffer() não reduz a memória máxima: o arquivo inteiro deve ser analisado. Para arquivos grandes (> 100 MB), certifique-se de que seu processo Node.js tenha heap suficiente: node --max-old-space-size=4096 yourScript.js.

Erros de tipo: ’entity’ é do tipo ‘unknown’ O entity propriedade é tipada de forma ampla. Converta para any ou para uma classe específica (Mesh, Camera, etc.) dependendo do que você espera em sua cena.

Perguntas Frequentes (FAQ)

Quais formatos podem ser carregados com scene.open()? OBJ, glTF 2.0 (.gltf + .bin), GLB, STL, 3MF, FBX e COLLADA (.dae) são todos suportados para importação. Passe a *LoadOptions classe correspondente a cada formato.

Posso carregar um arquivo sem especificar opções? Sim. scene.open('model.glb') funciona sem opções para formatos que não exigem configuração especial. Passar opções é recomendado para OBJ porque a resolução do material depende de enableMaterials.

O carregamento ocorre de forma assíncrona? Não. scene.open() e scene.openFromBuffer() são síncronos. Envolva-os em uma thread de trabalho ou setImmediate se precisar manter o loop de eventos responsivo.

A exportação OBJ é suportada? Sim. A exportação OBJ é suportada via scene.save('output.obj'). O .mtl arquivo de material é escrito automaticamente ao lado do .obj arquivo.

Onde o arquivo .mtl é esperado ao carregar OBJ? Por padrão, o parser procura o .mtl arquivo referenciado dentro do OBJ (mtllib diretiva) relativo ao diretório do arquivo OBJ. Certifique-se de que ambos os arquivos estejam na mesma pasta.

Veja também

 Português