Gráfico de cena

A. - Não . gráfico de cena é o modelo de dados básico do Aspose.3D FOSS para Python. Cada arquivo 3D, seja carregado a partir de disco ou construído na memória, é representado como uma árvore de Node objetos enraizados em: Scene.root_node.Cada nó pode conter um ou mais nós filhos e um (ou mais) nós de descendência . Entity Compreender o gráfico da cena dá-lhe acesso direto à geometria, materiais e transformações espaciais de cada objeto em uma cena.

Instalação e configuração

Instalar a biblioteca do PyPI:

asposefoss/3d is not yet published — build from source until it ships. See the project README for build instructions.

Não são necessárias extensões nativas, compiladores ou pacotes de sistema adicionais. Para instruções completas de instalação, consulte o Guia de instalação.


Resumo: Conceitos de gráfico da cena

O gráfico de cena em Aspose.3D FOSS segue uma hierarquia simples de contenção:

Scene
└── root_node  (Node)
    ├── child_node_A  (Node)
    │   ├── entity: Mesh
    │   └── transform: translation, rotation, scale
    ├── child_node_B  (Node)
    │   └── child_node_C  (Node)
    │       └── entity: Mesh
    └── ...
Objeto:Função
SceneContainer de nível superior. root_node, asset_info, animation_clips, e sub_scenes.
NodeNomeado nó de árvore. Tem um pai, zero ou mais filhos, 0 ou más entidades e uma local Transform.
EntityObjeto de geometria ou cena ligado a um nó. Tipos comuns: Mesh, Camera, Light.
TransformA posição no espaço local, rotação e escala para um nó. O resultado do espaço mundial é lido a partir de: global_transform.

Passo a passo: Construir um gráfico de cena programaticamente

Passo 1: Faça uma cena

Um novo Scene Começa sempre com um vazio. root_node:

from aspose.threed import Scene

scene = Scene()
print(scene.root_node.name)   # "" (empty string — root node has no name by default)
print(len(scene.root_node.child_nodes))  # 0

Scene é o ponto de entrada para tudo: carregamento de arquivos, salvar arquivo, criar clipes de animação e acessar a árvore do nó.


Passo 2: Criar Nodos Filhos

Utilização: create_child_node(name) para adicionar nós com nomes à árvore:

from aspose.threed import Scene

scene = Scene()

parent = scene.root_node.create_child_node("parent")
child  = parent.create_child_node("child")

print(parent.name)                          # "parent"
print(child.parent_node.name)               # "parent"
print(len(scene.root_node.child_nodes))     # 1

Em alternativa, crie um standalone Node e anexar explicitamente:

from aspose.threed import Scene, Node

scene = Scene()
node = Node("standalone")
scene.root_node.add_child_node(node)

Ambas as abordagens produzem o mesmo resultado. create_child_node é mais conciso para a construção em linha.


Passo 3: Criar uma entidade de malha e anexá-la

A. - Não . Mesh armazena dados de vértice (control_points) e topologia de face (polygons) Crie um, adicione geometria e anexe-o a um nó:

from aspose.threed import Scene, Node
from aspose.threed.entities import Mesh
from aspose.threed.utilities import Vector3, Vector4

scene = Scene()
parent = scene.root_node.create_child_node("parent")
child  = parent.create_child_node("child")

##Create a quad mesh (four vertices, one polygon)
# Note: control_points returns a copy of the internal list; append to
# _control_points directly to actually add vertices. This is a known
# library limitation — a public add_control_point() API is not yet available.
mesh = Mesh("cube")
mesh._control_points.append(Vector4(0, 0, 0, 1))
mesh._control_points.append(Vector4(1, 0, 0, 1))
mesh._control_points.append(Vector4(1, 1, 0, 1))
mesh._control_points.append(Vector4(0, 1, 0, 1))
mesh.create_polygon(0, 1, 2, 3)

child.add_entity(mesh)

print(f"Mesh name:      {mesh.name}")
print(f"Vertex count:   {len(mesh.control_points)}")
print(f"Polygon count:  {mesh.polygon_count}")

Vector4(x, y, z, w) representa uma coordenada homogênea. w=1 para posições regulares de pontos.

create_polygon(*indices) Aceita índices de vértices e registra uma face na lista de polígonos. Passa três índice para um triângulo, quatro para o quadrado.


Passo 4: Configurar transformações de nó

Cada nó tem um Transform que controla a sua posição, orientação e dimensão no espaço local:

from aspose.threed.utilities import Vector3, Quaternion

##Translate the node 2 units along the X axis
child.transform.translation = Vector3(2.0, 0.0, 0.0)

##Scale the node to half its natural size
child.transform.scaling = Vector3(0.5, 0.5, 0.5)

##Rotate 45 degrees around the Y axis using Euler angles (values are in radians)
import math
child.transform.euler_angles = Vector3(0.0, math.radians(45), 0.0)

As transformações são cumulativas: a posição de um nó filho no espaço-mundo é a composição da sua própria transformação com todas as transformaciones ancestrais. Leia o resultado avaliado do espaço mundial a partir de node.global_transform (imutável, somente para leitura).


Passe o gráfico da cena de forma recorrente.

Caminhe pela árvore inteira recorrendo-a . node.child_nodes:

def traverse(node, depth=0):
    indent = "  " * depth
    entity_type = type(node.entity).__name__ if node.entity else "None"
    print(f"{indent}{node.name} [{entity_type}]")
    for child in node.child_nodes:
        traverse(child, depth + 1)

traverse(scene.root_node)

Exemplo de saída para a cena construída acima (nome do nó raiz é uma cadeia vazia):

 [None]
  parent [None]
    child [Mesh]

Para cenas com múltiplas entidades por nó, iterar node.entities em vez de: node.entity:

def traverse_full(node, depth=0):
    indent = "  " * depth
    entity_names = [type(e).__name__ for e in node.entities] or ["None"]
    print(f"{indent}{node.name} [{', '.join(entity_names)}]")
    for child in node.child_nodes:
        traverse_full(child, depth + 1)

traverse_full(scene.root_node)

Passo 6: Salve a cena

Passe um caminho de arquivo para: scene.save().O formato é inferido da extensão de arquivo:

scene.save("scene.gltf")   # JSON glTF 2.0
scene.save("scene.glb")    # Binary GLB container
scene.save("scene.obj")    # Wavefront OBJ
scene.save("scene.stl")    # STL

Para opções específicas de formato, passar um objeto “save-options” como segundo argumento:

from aspose.threed.formats import GltfSaveOptions

opts = GltfSaveOptions()
scene.save("scene.gltf", opts)

Dicas e melhores práticas

  • Nomear cada nó. Dar nomes significativos aos nós torna os depuradores muito mais fáceis e garante que os nomes sejam preservados no arquivo exportado.
  • Uma malha por nó. Manter entidades 1:1 com nós simplifica transformações e consultas de colisão.
  • Utilização: create_child_node sobre a fixação manual. Estabelece automaticamente a referência principal e é menos propensa a erros.
  • Leia. global_transform Depois de construir a hierarquia. O resultado do espaço-mundo só é estável quando todas as transformações ancestrais estão definidas.
  • Não mude a árvore durante o traçado. Adicionar ou remover nós filhos durante a iteração child_nodes Coletar os nós primeiro, depois modificar.
  • Utilização dos pontos de controlo Vector4, não . Vector3. Sempre passar . w=1 para posições de vértices ordinários; w=0 representa um vetor de direcção (não é um ponto).
  • mesh.control_points devolve uma cópia. A Comissão control_points declarações de propriedade list(self._control_points) o anexo à lista devolvida não altera a malha. mesh._control_points Esta é uma limitação conhecida da biblioteca; ainda não existe uma API de mutação pública.

Problemas comuns

EmissãoResolução
AttributeError: 'NoneType' object has no attribute 'polygons'Guarda com if node.entity is not None Um nó sem entidades tem entity = None.
A malha aparece na origem apesar de se colocar. translationtransform.translation aplica um deslocamento local. Se o nó padrão tiver uma transformação não-identidade, a posição mundial pode diferir. Verifique global_transform.
Nódulos infantis desaparecidos depois de scene.save() / recarregamentoAlguns formatos (OBJ) achatam a hierarquia. Use glTF ou COLLADA para preservar a árvore completa do nó.
polygon_count é 0 depois de mesh.create_polygon(...)Verifique se os índices de vértices passaram para o create_polygon estão dentro do alcance (0 a) para o len(control_points) - 1).
Node.get_child(name) Renda de rendimentos NoneO nome é sensível a maiúsculas. Confirme o nome exato usado no momento da criação.
Visitas transversais a nós em ordem inesperadachild_nodes retorna crianças em ordem de inserção (a ordem add_child_node / create_child_node foi chamado).

Ver também:

 Português