Trabalhar com o gráfico de cena
Todo o conteúdo 3D em Aspose.3D FOSS para TypeScript vive dentro de um Scene objeto organizado como uma árvore de Node Entender esta hierarquia é a base para construir, carregar e processar qualquer arquivo 3D.
Instalação
Instale o pacote a partir do npm antes de executar qualquer um dos códigos deste guia:
asposefoss/3d is not yet published — build from source until it ships. See the project README for build instructions.Assegure-se de que o seu tsconfig.json inclui: "module": "commonjs" e a) "moduleResolution": "node" para a resolução correta de importação por sub-pista.
Conceitos de gráfico de cena
O gráfico de cena tem três níveis:
| Nível de avaliação | Classe: | Função |
|---|---|---|
| Escenário | Scene | Container de nível superior. rootNode, animationClips, e assetInfo. |
| Nodo de ligação | Node | Pode ter nós filhos, uma entidade, um transformador e materiais. |
| Emissão de dados | Mesh, Camera, Light, … | Conteúdo ligado a um nó. Um nó carrega no máximo uma entidade. |
A cadeia de herança dos principais elementos é a seguinte:
A3DObject
└─ SceneObject
├─ Node (tree structure)
└─ Entity
└─ Geometry
└─ Mesh (polygon geometry)scene.rootNode Não o cria manualmente, você cria nós filhos por baixo dele.
Passo 1: Faça uma cena
import { Scene } from '@aspose/3d';
const scene = new Scene();
console.log(scene.rootNode.name); // '' (empty string — the root node is created with no name)
Um novo Scene Começa com um nó raiz vazio e sem clipes de animação. Você constrói conteúdo anexando nós filhos.
Passo 2: Adicionar Nodos Filhos
Utilização: createChildNode() O método retorna o novo Node, para poderem fazer chamadas de qualquer nível:
import { Scene } from '@aspose/3d';
const scene = new Scene();
const parent = scene.rootNode.createChildNode('parent');
const child = parent.createChildNode('child');
console.log(scene.rootNode.childNodes.length); // 1 (parent)
console.log(parent.childNodes.length); // 1 (child)
Nomes de nós são strings arbitrários. Os nomes não precisam ser únicos, mas usar nomes significativos torna o código de travessagem mais fácil de depurar.
Passo 3: Criar uma malha e definir vértices
Mesh é a classe de geometria primária. Adicionar posições vértices pressionando Vector4 valores em mesh.controlPoints,Então , liga-me . createPolygon() para definir as faces por índice de vértices:
import { Scene } from '@aspose/3d';
import { Mesh } from '@aspose/3d/entities';
import { Vector4 } from '@aspose/3d/utilities';
const scene = new Scene();
const child = scene.rootNode.createChildNode('parent').createChildNode('child');
const mesh = new Mesh('cube');
mesh.controlPoints.push(new Vector4(0, 0, 0, 1));
mesh.controlPoints.push(new Vector4(1, 0, 0, 1));
mesh.controlPoints.push(new Vector4(1, 1, 0, 1));
mesh.controlPoints.push(new Vector4(0, 1, 0, 1));
mesh.createPolygon(0, 1, 2, 3); // quad face using all four vertices
child.entity = mesh;
console.log(mesh.controlPoints.length); // 4
console.log(mesh.polygonCount); // 1
Vector4 utiliza coordenadas homogéneas: o w componente é: 1 para posições e 0 para vetores de direcção.
Passo 4: Configurar transformações de nó
Cada nó tem um transform propriedade com translation, rotation, e scaling.- Está pronto . translation para mover o nó em relação ao seu núcleo-mãe:
import { Scene } from '@aspose/3d';
import { Mesh } from '@aspose/3d/entities';
import { Vector4, Vector3 } from '@aspose/3d/utilities';
const scene = new Scene();
const parent = scene.rootNode.createChildNode('parent');
const child = parent.createChildNode('child');
const mesh = new Mesh('cube');
mesh.controlPoints.push(new Vector4(0, 0, 0, 1));
mesh.controlPoints.push(new Vector4(1, 0, 0, 1));
mesh.controlPoints.push(new Vector4(1, 1, 0, 1));
mesh.controlPoints.push(new Vector4(0, 1, 0, 1));
mesh.createPolygon(0, 1, 2, 3);
child.entity = mesh;
child.transform.translation = new Vector3(2.0, 0.0, 0.0);globalTransform fornece a matriz de transformação do espaço-mundo (somente leitura), calculada por concatenando todas as transformações ancestrais.
Passo 5: Atravesse a árvore
Escreva uma função recursiva para visitar cada nó. Verifique node.entity e a) node.childNodes em cada nível:
function traverse(node: any, depth = 0): void {
const indent = ' '.repeat(depth);
const entityType = node.entity ? node.entity.constructor.name : 'none';
console.log(`${indent}${node.name} [${entityType}]`);
for (const child of node.childNodes) {
traverse(child, depth + 1);
}
}
traverse(scene.rootNode);Para a hierarquia criada acima, o resultado será:
[none]
parent [none]
child [Mesh]O nome do nó raiz é uma cadeia vazia porque Scene cria-o sem argumento de nome.
Sempre proteja o acesso de entidades com uma verificação nula antes de lançar para um tipo específico. Nem todos os nós carregam uma entidade.
Etapa 6: Salvar para o GLTF ou GLB
Utilização: GltfSaveOptions Para controlar o formato de saída. binaryMode = true para produzir um único auto-contido, .glb Arquivo; deixe-o. false para o JSON .gltf + .bin Par de sidecar:
import { Scene } from '@aspose/3d';
import { Mesh } from '@aspose/3d/entities';
import { Vector4, Vector3 } from '@aspose/3d/utilities';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
const parent = scene.rootNode.createChildNode('parent');
const child = parent.createChildNode('child');
const mesh = new Mesh('cube');
mesh.controlPoints.push(new Vector4(0, 0, 0, 1));
mesh.controlPoints.push(new Vector4(1, 0, 0, 1));
mesh.controlPoints.push(new Vector4(1, 1, 0, 1));
mesh.controlPoints.push(new Vector4(0, 1, 0, 1));
mesh.createPolygon(0, 1, 2, 3);
child.entity = mesh;
child.transform.translation = new Vector3(2.0, 0.0, 0.0);
const saveOpts = new GltfSaveOptions();
saveOpts.binaryMode = true; // write a single .glb file
scene.save('scene.glb', GltfFormat.getInstance(), saveOpts);
console.log('Scene saved to scene.glb');Passagem . GltfFormat.getInstance() como o argumento de formato, então a biblioteca usa o codificador correto independentemente da extensão do arquivo.
Dicas e melhores práticas
- Utilização:
createChildNode()Em vez de construirNodedireta:createChildNode()automaticamente liga a relação pai-filho e registra o nó na árvore. - Verificação
node.entityantes de aceder às propriedades da entidade: muitos nós (nodes de grupo, ossos, localizadores) não carregam nenhuma entidade. Sempre proteja com uma verificação nula ouinstanceofteste. - Set (s)
translationEm nós filhos, não em vértices de malha: modificaçãotransform.translationNão é destrutivo e composto com as transformações-mãe. - Preferência
binaryMode = truepara o GLB:Uma única:.glbarquivo é mais fácil de distribuir, carregar em navegadores e importar para motores de jogo do que o split.gltf+.binformato. - Via de travessão
for...ofmais uma vez .childNodes: evitar a indexação numérica; utilizar o iterável directamente para compatibilidade com os futuros.
Problemas comuns
| Sintoma: | Causa provável | Correção |
|---|---|---|
child.entity = mesh não tem efeito sobre as exportações. | Entidade atribuída ao nível de nó errado | Acompanhar entity para o nó de folhas, não para um nó do grupo |
node.entity é sempre null | Só a verificar. rootNode a si mesma | Recorrer a: node.childNodes; rootNode normalmente não tem entidade |
| Transformação não refletida no visor GLB | globalTransform não actualizado | globalTransform é calculado em salvar; set transform.translation Antes de ligares. scene.save() |
O GLB produz um sistema de gestão separado. .bin Carrinho lateral | binaryMode Descontos para false | Set (s) saveOpts.binaryMode = true |
Ver também:
- Características e funcionalidades: referência completa da API para todas as áreas de características.
- Suporte de formato: formatos 3D suportados, capacidade de leitura/escrita e opções de formato.
- Como construir uma malha 3D programaticamente
- Aspose.3D para TypeScript Documentação Empresarial