Graf scény
A. Vypravit . Scénový graf je základní datový model Aspose.3D FOSS pro Python. Každý 3D soubor, ať už naložený z disku nebo konstruovaný v paměti, je reprezentován jako strom s Node objekty zakořeněné v Scene.root_node.Každý uzel může obsahovat dětské uzly a jeden nebo více . Entity Pochopení grafu scény vám dává přímý přístup k geometrii, materiálům a prostorovým transformacím každého objektu v scéně.
Instalace a nastavení
Nainstalovat knihovnu z PyPI:
asposefoss/3d is not yet published — build from source until it ships. See the project README for build instructions.Pro úplné instalační pokyny viz návod na instalaci. Příručka pro instalaci.
Přehled: Koncepce grafu scén
Graf scény v Aspose.3D FOSS následuje jednoduchou hierarchii zajištění:
Scene
└── root_node (Node)
├── child_node_A (Node)
│ ├── entity: Mesh
│ └── transform: translation, rotation, scale
├── child_node_B (Node)
│ └── child_node_C (Node)
│ └── entity: Mesh
└── ...| Předmět: | Úloha: |
|---|---|
Scene | Kontejner nejvyšší úrovně. root_node, asset_info, animation_clips,a) sub_scenes. |
Node | Jmenovaný stromový uzel. Má rodiče, nulové nebo více dětí, nula nebo víc entit a místní Transform. |
Entity | Geometrie nebo objekt scény připojený k uzlu. Typy běžných subjektů: Mesh, Camera, Light. |
Transform | Místní poloha, rotace a rozměry pro uzel. Výsledek světového prostoru se čte z global_transform. |
Krok za krokem: Programaticky vytvářet grafický graf scény
Krok 1: Vytvořte scénu
Nový . Scene Vždycky začíná prázdnou. 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)) # 0Scene je vstupním bodem pro všechno: načítání souborů, ukládání dat, vytváření animačních klipů a přístup k stromku uzlů.
Krok 2: Vytvořit dětské uzly
Použití: create_child_node(name) přidat do stromu jmenované uzly:
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)) # 1Nebo vytvořte samostatný Node a výslovně připojte:
from aspose.threed import Scene, Node
scene = Scene()
node = Node("standalone")
scene.root_node.add_child_node(node)Oba přístupy vedou k stejnému výsledku. create_child_node je stručnější pro konstrukci v řadě.
Krok 3: Vytvořte entitu sítě a připojte ji
A. Vypravit . Mesh ukládá data o vrcholu (control_points) a topologie obličeje (polygons) Vytvořte jeden, přidejte geometrii a připojte ho k uzlu:
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) představuje homogenní souřadnice. w=1 pro pravidelné bodové pozice.
create_polygon(*indices) Přijímá indexy vrcholu a zaznamenává jednu stranu v seznamu polygonů.
Krok 4: Nastavit transformace uzlů
Každý uzel má Transform které řídí jeho polohu, orientaci a velikost v místním prostoru:
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
child.transform.euler_angles = Vector3(0.0, 45.0, 0.0)Transformace jsou kumulativní: pozice dětského uzlu ve světovém prostoru je složení jeho vlastní transformace se všemi předky. Přečtěte si vyhodnocovaný výsledek světo-prostoru z node.global_transform (nezměnný, pouze pro čtení).
Krok 5: Překračujte scénový graf rekurzivně.
Procházíte celou stromu opakováním. 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)Příklad výstupu pro scénu postavenou výše (jméno kořenového uzlu je prázdný řetěz):
[None]
parent [None]
child [Mesh]Pro scény s více entitami na uzel, iterovat node.entities místo: 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)Krok 6: Uložte scénu
Přeneste cestu souboru na … scene.save().Formát je odvozen z rozšíření souboru:
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") # STLPro formátově specifické možnosti předá jako druhý argument objekt “save-options”:
from aspose.threed.formats import GltfSaveOptions
opts = GltfSaveOptions()
scene.save("scene.gltf", opts)Tipy a nejlepší postupy
- Pojmenujte každý uzel. Dání uzlům smysluplných jmen usnadňuje odstraňování travaux a zajišťuje, že jména jsou uchovávána v exportovaném souboru.
- Jedna síť na uzel. Udržování entit 1:1 s uzly zjednodušuje transformace a kolizní dotazy.
- Použití:
create_child_nodepřes ruční připojení. Nastavuje automaticky základní odkaz a je méně náchylný k chybám. - Čtěte.
global_transformPo vytvoření hierarchie. Výsledek světového prostoru je stabilní jen tehdy, když jsou nastaveny všechny předkové transformace. - Nezmetujte strom během průchodu. Přidávání nebo odstranění dětských uzlů při iterování
child_nodesNejprve seberte uzly, pak je upravíte. - Použití kontrolních bodů
Vector4, ne .Vector3. Vždycky projít.w=1pro běžné pozice vrcholu;w=0představuje směrový vektor (ne bod). mesh.control_pointsvrátí kopii. Úřad pro bezpečnost a ochranu zdravícontrol_pointsvýdaje z majetkulist(self._control_points)připojení k vrácenému seznamu nemění síť. Vždy přidávejte domesh._control_pointsJe to známé omezení knihovny; veřejná mutační API ještě neexistuje.
Obvyklé problémy
| Výše: | Rozhodnutí |
|---|---|
AttributeError: 'NoneType' object has no attribute 'polygons' | Stráž s: if node.entity is not None před přístupem k vlastnostem entit. Vstup bez entit má entity = None. |
Ošáky se objevují na původu i přes nastavení. translation | transform.translation Pokud má samotný mateřský uzel transformovanou bez identity, může se světová pozice lišit. Zkontrolujte global_transform. |
Dítě ztratil uzly po scene.save() / přeložit | Některé formáty (OBJ) plošní hierarchii. Použijte glTF nebo COLLADA k zachování plného stromu uzlu. |
polygon_count je 0 po mesh.create_polygon(...) | Ověřte, zda indexy vrcholu přešly na: create_polygon jsou v dosahu (0 na … len(control_points) - 1). |
Node.get_child(name) výnosy None | Název je citlivý na velké písmená. Potvrďte přesný řetěz jména použitý při vytváření. |
| Průběžné návštěvy uzlů v neočekávaném pořadí | child_nodes vrací děti v pořadí vložení (pořadím, které je uvedeno na seznamu) add_child_node / create_child_node byla nazvaná). |