Recursos e Funcionalidades
Aspose.3D FOSS for TypeScript é uma biblioteca Node.js licenciada sob MIT para carregar, construir e exportar cenas 3D. Ela inclui definições de tipo TypeScript completas, uma única dependência em tempo de execução (xmldom),.
Instalação e Configuração
Instale o pacote a partir do npm usando um único comando:
npm install @aspose/3dO pacote tem como alvo CommonJS e requer Node.js 18 ou superior. Após a instalação, verifique seu tsconfig.json inclui as seguintes opções de compilador para total compatibilidade:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true
}
}Importe o principal Scene classe a partir da raiz do pacote. Classes de opções específicas de formato são importadas de seus respectivos subcaminhos:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';Recursos e Funcionalidades
Suporte a Formatos
Aspose.3D FOSS for TypeScript lê e grava seis principais formatos de arquivo 3D. A detecção de formato é automática a partir dos números mágicos binários ao carregar, portanto você não precisa especificar o formato de origem explicitamente.
| Formato | Leitura | Gravação | Observações |
|---|---|---|---|
| OBJ (Wavefront) | Sim | Sim | Lê/escreve .mtl materiais; uso ObjLoadOptions.enableMaterials para import |
| glTF 2.0 | Sim | Sim | Formato de texto JSON; materiais PBR |
| GLB | Sim | Sim | Binary glTF; definido GltfSaveOptions.binaryMode = true |
| STL | Sim | Sim | Binary e ASCII; roundtrip completo verificado |
| 3MF | Sim | Sim | 3D Manufacturing Format with color and material metadata |
| FBX | Não* | Não* | Importador/exportador existem, mas a detecção automática de formato não está conectada |
| COLLADA (DAE) | Sim | Sim | Escala de unidades, geometria, materiais e clipes de animação |
Carregando OBJ com materiais:
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);Salvando para GLB (glTF binário):
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);Grafo de Cena
Todo o conteúdo 3D é organizado como uma árvore de Node objetos enraizados em scene.rootNode. Cada nó pode carregar um Entity (um Mesh, Camera, Light, ou outro SceneObject) e um Transform que o posiciona em relação ao seu pai.
Classes principais do grafo de cena:
Scene: o contêiner de nível superior; contémrootNodeeanimationClipsNode: um nó de árvore nomeado comchildNodes,entity,transform, ematerialsEntity: classe base para objetos anexáveis (Mesh,Camera,Light)SceneObject: classe base compartilhada porNodeeEntityA3DObject: classe base raiz comnamee conjunto de propriedadesTransform: translação local, rotação (Euler e Quaternion) e escala
Percorrendo o grafo de cena:
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);Criando uma hierarquia de cena programaticamente:
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 Malha
Mesh é o tipo de geometria principal. Ele estende Geometry e expõe pontos de controle (vértices), índices de polígonos e elementos de vértice para normais, UVs e cores de vértice.
Classes principais de geometria:
Mesh: malha poligonal comcontrolPointsepolygonCountGeometry: classe base com gerenciamento de elementos de vérticeVertexElementNormal: normais por vértice ou por vértice de polígonoVertexElementUV: coordenadas de textura (um ou mais canais UV)VertexElementVertexColor: dados de cor por vérticeMappingMode: controla como os dados do elemento são mapeados para polígonos (CONTROL_POINT,POLYGON_VERTEX,POLYGON,EDGE,ALL_SAME)ReferenceMode: controla a estratégia de indexação (DIRECT,INDEX,INDEX_TO_DIRECT)VertexElementType: identifica a semântica de um elemento de vérticeTextureMapping: enumeração de canais de textura
Lendo dados de malha de uma cena carregada:
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 de Material
Aspose.3D FOSS para TypeScript suporta três tipos de material que cobrem toda a gama, desde sombreamento Phong legado até renderização baseada em física:
LambertMaterial: cor difusa e cor ambiente; mapeia para materiais simples OBJ/DAEPhongMaterial: adiciona cor especular, brilho e emissivo; o tipo de material OBJ padrãoPbrMaterial: modelo fisicamente baseado de rugosidade/metallic; usado para importação e exportação glTF 2.0
Lendo materiais de uma cena OBJ carregada:
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)}`);
}
}
}Aplicando um material PBR ao construir uma cena 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);Utilitários Matemáticos
A biblioteca vem com um conjunto completo de tipos matemáticos 3D, todos totalmente tipados:
Vector3: vetor de 3 componentes; suportaminus(),times(),dot(),cross(),normalize(),length,angleBetween()Vector4: vetor de 4 componentes para coordenadas homogêneasMatrix4: matriz de transformação 4×4 comconcatenate(),transpose,decompose,setTRSQuaternion: quaternion de rotação comfromEulerAngle(): (estático, singular),eulerAngles(): (método de instância),slerp(),normalize()BoundingBox: caixa delimitadora alinhada aos eixos comminimum,maximum,center,size,mergeFVector3: variante de precisão simples deVector3: usado em dados de elemento de vértice
Computando uma caixa delimitadora a partir dos vértices da malha:
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);Construindo uma transformação a partir de ângulos de Euler:
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 de Animação
A API de animação modela clipes, nós, canais e sequências de quadros‑chave:
AnimationClip: coleção nomeada de nós de animação; acessada viascene.animationClips;: ; expõeanimations: AnimationNode[]AnimationNode: grupo nomeado deBindPoints; criado viaclip.createAnimationNode(name), acessado viaclip.animationsBindPoint: vincula umAnimationNodea uma propriedade específica em um objeto de cena; expõepropertyechannelsCountAnimationChannel: estendeKeyframeSequence; contém um separadokeyframeSequence; acessado viabindPoint.getChannel(name)KeyFrame: um único par tempo/valor; carrega por-keyframeinterpolation: InterpolationKeyframeSequence: lista ordenada deKeyFrameobjetos viakeyFrames; tempreBehaviorepostBehavior(Extrapolation)Interpolation: enum:LINEAR,CONSTANT,BEZIER,B_SPLINE,CARDINAL_SPLINE,TCB_SPLINEExtrapolation: classe comtype: ExtrapolationTypeerepeatCount: numberExtrapolationType: enum:CONSTANT,GRADIENT,CYCLE,CYCLE_RELATIVE,OSCILLATE
Lendo dados de animação de uma cena carregada:
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}`);
}
}
}Suporte a Stream e Buffer
Use scene.openFromBuffer() para carregar uma cena 3D diretamente da memória Buffer. Este é o padrão recomendado para funções serverless, pipelines de streaming e processamento de ativos obtidos via HTTP sem gravar em 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);
}
}A detecção automática de formato a partir de números mágicos binários se aplica ao carregar a partir de buffer, de modo que arquivos GLB, STL binário e 3MF são reconhecidos sem a necessidade de especificar um parâmetro de formato.
Exemplos de Uso
Exemplo 1: Carregar OBJ e Exportar para GLB
Este exemplo carrega um arquivo Wavefront OBJ com materiais e, em seguida, reexporta a cena como um arquivo glTF binário (GLB) adequado para uso na web e em motores de jogo.
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');Exemplo 2: Ida e Volta STL com Validação de Normais
Este exemplo carrega um arquivo STL binário, imprime informações de normais por vértice e, em seguida, reexporta a cena como STL ASCII e verifica a ida e volta.
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);Exemplo 3: Construir uma Cena Programaticamente e Salvar como glTF
Este exemplo constrói uma cena com um material PBR do zero e a salva como um arquivo 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');Dicas e Melhores Práticas
- Use
ObjLoadOptions.enableMaterials = truesempre que precisar de dados de material de arquivos .mtl. Sem ele, a lista de materiais em cada nó ficará vazia. - Prefira
binaryMode = truepara GLB ao produzir ativos para web ou motores de jogo. O GLB binário é um único arquivo autônomo e carrega mais rápido em navegadores e motores do que a divisão JSON + .bin. - Use
openFromBuffer()em ambientes serverless para evitar I/O de arquivos temporários. Busque o ativo, passe oBufferdiretamente, e escreva a saída em um stream ou outro buffer. - Verifique
node.entityantes de converter: nem todos os nós contêm uma entidade. Sempre proteja com uminstanceofverifique antes de acessarMesh-propriedades específicas comocontrolPoints. - Definir
normalizeNormal = trueemObjLoadOptionsquando seus arquivos OBJ de origem provêm de fontes não confiáveis. Isso impede que normais degeneradas se propaguem para etapas subsequentes de renderização ou validação. - Mantenha
strict: trueem tsconfig.json: a biblioteca é desenvolvida comnoImplicitAnyestrictNullChecks. Desativandostrictoculta erros de tipo reais e anula o valor da API tipada. - Percorrer via
childNodes, não um loop de índice: ochildNodespropriedade retorna um iterável; evite depender da indexação numérica para compatibilidade futura.
Problemas Comuns
| Sintoma | Causa provável | Correção |
|---|---|---|
| Lista de materiais vazia após carregamento de OBJ | enableMaterials não definido | Definir options.enableMaterials = true |
| Arquivo GLB contém um sidecar .bin separado | binaryMode usando como padrão false | Definir opts.binaryMode = true |
| Normais de vértice ausentes na saída STL | O modo ASCII do STL omite normais por face | Mudar para binaryMode = true ou calcular as normais antes da exportação |
node.entity é sempre null | Percorrendo apenas rootNode, não seus filhos | Recursar em node.childNodes |
| Erro do TypeScript: a propriedade não existe | Antigo @types cache | Executar npm install @aspose/3d novamente; sem separado @types pacote é necessário |
openFromBuffer lança erro de formato | Formato não detectável automaticamente a partir do magic | Passe a classe de opção de formato explícita como segundo argumento |
Perguntas Frequentes
A biblioteca requer algum addon nativo ou pacotes do sistema? Não. Aspose.3D FOSS for TypeScript tem uma única dependência em tempo de execução: xmldom, que é puro JavaScript e instalado automaticamente pelo npm. Não há .node addons nativos e sem pacotes de sistema para instalar.
Quais versões do Node.js são suportadas? Node.js 18, 20 e 22 LTS. A biblioteca tem como alvo saída CommonJS e usa recursos de linguagem ES2020 internamente.
Posso usar a biblioteca em um bundle de navegador (webpack/esbuild)? A biblioteca tem como alvo Node.js e usa o Node.js fs e Buffer APIs. O empacotamento para navegador não é oficialmente suportado. Para uso em navegador, carregue a cena no servidor e transmita o resultado (por exemplo, como GLB) ao cliente.
Qual é a diferença entre GltfSaveOptions.binaryMode = true e false? binaryMode = false produz um .gltf arquivo JSON mais um separado .bin sidecar de buffer binário. binaryMode = true produz um único auto-contido .glb arquivo. Use true para entrega de ativos em produção.
Posso carregar um arquivo a partir de uma resposta HTTP sem salvá-lo no disco? Sim. Busque a resposta como um Buffer (por exemplo, usando node-fetch ou o incorporado fetch no Node 18+), então chame scene.openFromBuffer(buffer, options).
O suporte a FBX está completo? Não. As classes de importação e exportação de FBX existem na biblioteca, mas o FBX não está integrado ao Scene.open() ou Scene.save() detecção automática. Chamando scene.open('file.fbx') não invocará o importador FBX; o arquivo será tratado pelo caminho de fallback STL. Use as classes importador/exportador específicas para FBX diretamente se precisar de I/O FBX. Veja a tabela de suporte a formatos acima que marca FBX como No*.
A biblioteca suporta TypeScript 4.x? TypeScript 5.0+ é recomendado. TypeScript 4.7+ deve funcionar na prática, mas a biblioteca é testada e desenvolvida para 5.0+.
Resumo da Referência da API
| Classe | Módulo | Propósito |
|---|---|---|
Scene | @aspose/3d | Contêiner de cena de nível superior; open(), openFromBuffer(), save(), rootNode, animationClips |
Node | @aspose/3d | Nó do grafo de cena; childNodes, entity, transform, materials, createChildNode() |
Entity | @aspose/3d | Classe base para objetos que podem ser anexados à cena |
SceneObject | @aspose/3d | Classe base compartilhada por Node e Entity |
A3DObject | @aspose/3d | Base raiz com name e conjunto de propriedades |
Transform | @aspose/3d | Translação, rotação e escala locais |
Mesh | @aspose/3d | Malha poligonal; controlPoints, polygonCount, createPolygon(), elementos de vértice |
Geometry | @aspose/3d | Classe base para tipos de geometria |
Camera | @aspose/3d | Entidade de câmera com campo de visão e configurações de projeção |
Light | @aspose/3d | Entidade de luz (ponto, direcional, spot) |
LambertMaterial | @aspose/3d | Modelo de sombreamento difuso + ambiente |
PhongMaterial | @aspose/3d | Sombreamento Phong com especular e emissivo |
PbrMaterial | @aspose/3d | Modelo fisicamente baseado de rugosidade/metallic para 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 | Quaternion de rotação |
BoundingBox | @aspose/3d | Caixa delimitadora alinhada aos eixos |
FVector3 | @aspose/3d | Variante de precisão simples de Vector3 |
VertexElementNormal | @aspose/3d | Normais por vértice ou por vértice de polígono |
VertexElementUV | @aspose/3d | Elemento de vértice de coordenada de textura |
VertexElementVertexColor | @aspose/3d | Elemento de vértice de cor por vértice |
MappingMode | @aspose/3d | Enum: CONTROL_POINT, POLYGON_VERTEX, POLYGON, ALL_SAME |
ReferenceMode | @aspose/3d | Enum: DIRECT, INDEX, INDEX_TO_DIRECT |
AnimationClip | @aspose/3d | Animação nomeada; expõe animations: AnimationNode[]; criado via scene.createAnimationClip(name) |
AnimationNode | @aspose/3d | Grupo nomeado de BindPoints; criado via clip.createAnimationNode(name) |
BindPoint | @aspose/3d | Vincula um AnimationNode a uma propriedade de objeto de cena; expõe property e channelsCount |
AnimationChannel | @aspose/3d | Estende KeyframeSequence; contém um keyframeSequence; acessado via bindPoint.getChannel(name) |
KeyFrame | @aspose/3d | Par único de quadro-chave tempo/valor; carrega interpolation: Interpolation |
KeyframeSequence | @aspose/3d | Ordenado keyFrames lista; preBehavior/postBehavior são Extrapolation objetos |
Interpolation | @aspose/3d | Enum: LINEAR, CONSTANT, BEZIER, B_SPLINE, CARDINAL_SPLINE, TCB_SPLINE |
Extrapolation | @aspose/3d | Classe com type: ExtrapolationType e repeatCount: number |
ExtrapolationType | @aspose/3d | Enum: CONSTANT, GRADIENT, CYCLE, CYCLE_RELATIVE, OSCILLATE |
ObjLoadOptions | @aspose/3d/formats/obj | Opções de importação OBJ: enableMaterials, flipCoordinateSystem, scale, normalizeNormal |
GltfSaveOptions | @aspose/3d/formats/gltf | Opções de exportação glTF/GLB: binaryMode |
GltfFormat | @aspose/3d/formats/gltf | Instância de formato para glTF/GLB; passe para scene.save() |
StlLoadOptions | @aspose/3d/formats/stl | Opções de importação STL |
StlSaveOptions | @aspose/3d/formats/stl | Opções de exportação STL: binaryMode |
StlImporter | @aspose/3d/formats/stl | Leitor STL de baixo nível |
StlExporter | @aspose/3d/formats/stl | Gravador STL de baixo nível |