Jak načíst 3D modely v Python
Aspose.3D FOSS pro Python poskytuje jednoduché API pro otevírání 3D souborů bez jakýchkoli nativních závislostí. Po načtení souboru do Scene objektu můžete procházet hierarchii uzlů a číst surová geometrická data pro každou síť v scéně.
Průvodce krok za krokem
Krok 1: Nainstalujte balíček
Nainstalujte Aspose.3D FOSS z PyPI. Nejsou vyžadovány žádné další systémové knihovny.
pip install aspose-3d-fossPodporované verze Python: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.
Krok 2: Importujte třídu Scene
Třída Scene třída je kontejner nejvyšší úrovně pro všechna 3D data. Importujte ji spolu s libovolnými třídami pro načítací možnosti, které potřebujete.
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptionsVšechny veřejné třídy se nacházejí pod aspose.threed nebo v jejích podbalíčcích (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).
Krok 3: Načtěte soubor
Použijte statickou Scene.from_file() metodu k otevření libovolného podporovaného formátu. Knihovna detekuje formát automaticky podle přípony souboru.
##Automatic format detection
scene = Scene.from_file("model.obj")Alternativně vytvořte Scene instanci a zavolejte open(); užitečné, když chcete předat možnosti načítání nebo explicitně zpracovat chyby:
scene = Scene()
scene.open("model.obj")Obě metody podporují soubory OBJ, STL (binární i ASCII), glTF 2.0 / GLB, COLLADA (DAE) a 3MF.
Krok 4: Procházejte uzly scény
Načtená scéna je strom Node objektů kořeněných v scene.root_node. Procházejte rekurzivně, abyste našli všechny uzly:
from aspose.threed import Scene, Node
scene = Scene.from_file("model.obj")
def walk(node: Node, depth: int = 0) -> None:
indent = " " * depth
print(f"{indent}Node: {node.name!r}")
for child in node.child_nodes:
walk(child, depth + 1)
walk(scene.root_node)Každý Node může nést nula nebo více Entity objekty (meshes, kamery, světla). Zkontrolujte node.entities abyste zjistili, co je připojeno.
Krok 5: Přístup k datům vrcholů a polygonů
Přetypujte entitu uzlu na Mesh a přečtěte jeho kontrolní body (pozice vrcholů) a polygonů (seznamy indexů ploch):
from aspose.threed import Scene
from aspose.threed.entities import Mesh
scene = Scene.from_file("model.obj")
for node in scene.root_node.child_nodes:
for entity in node.entities:
if isinstance(entity, Mesh):
mesh: Mesh = entity
print(f"Mesh '{node.name}': "
f"{len(mesh.control_points)} vertices, "
f"{len(mesh.polygons)} polygons")
# First vertex position
if mesh.control_points:
v = mesh.control_points[0]
print(f" First vertex: ({v.x:.4f}, {v.y:.4f}, {v.z:.4f})")
# First polygon face (list of control-point indices)
if mesh.polygons:
print(f" First polygon: {mesh.polygons[0]}")mesh.control_points je seznam Vector4 objektů; x, y, z nesou pozici a w je homogenní souřadnice (obvykle 1.0).
mesh.polygons je seznam seznamů celých čísel, kde každý vnitřní seznam představuje uspořádanou sadu indexů řídicích bodů pro jednu plochu.
Krok 6: Použití formátově specifických možností načítání
Pro jemnozrnné řízení toho, jak je soubor OBJ interpretován, předávejte ObjLoadOptions instanci do scene.open():
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions
options = ObjLoadOptions()
options.flip_coordinate_system = True # Convert right-hand Y-up to Z-up
options.scale = 0.01 # Convert centimetres to metres
options.enable_materials = True # Load .mtl material file
options.normalize_normal = True # Normalize all normals to unit length
scene = Scene()
scene.open("model.obj", options)Pro soubory STL je ekvivalentní třída StlLoadOptions. Pro glTF použijte GltfLoadOptions. Viz referenci API pro úplný seznam.
Časté problémy a opravy
FileNotFoundError při volání Scene.from_file()
Cesta musí být absolutní nebo správně relativní k pracovnímu adresáři za běhu. Použijte pathlib.Path k vytvoření spolehlivých cest:
from pathlib import Path
from aspose.threed import Scene
path = Path(__file__).parent / "assets" / "model.obj"
scene = Scene.from_file(str(path))mesh.polygons je prázdný po načtení souboru STL
Soubory STL ukládají trojúhelníky jako surové fasety, nikoli jako indexovanou síť. Po načtení jsou z těchto faset syntetizovány polygonové tvary. Pokud polygons vypadá prázdně, zkontrolujte len(mesh.control_points); pokud je počet násobkem 3, geometrie je uložena v neindexované formě a každá po sobě jdoucí trojice vrcholů tvoří jeden trojúhelník.
Neshoda souřadnicového systému (model se jeví otočený nebo zrcadlený)
Různé nástroje používají různé konvence (Y-up vs Z-up, left-hand vs right-hand). Nastavte ObjLoadOptions.flip_coordinate_system = True nebo použijte rotaci na kořenovém uzlu Transform po načtení.
AttributeError: 'NoneType' object has no attribute 'polygons'
Seznam entit uzlu může obsahovat ne‑mesh entity (kamery, světla). Vždy jej chraňte pomocí isinstance(entity, Mesh) před přetypováním.
Často kladené otázky (FAQ)
Jaké 3D formáty mohu načíst?
OBJ (Wavefront), STL (binární i ASCII), glTF 2.0 / GLB, COLLADA (DAE) a 3MF. Tokenizace souborů FBX je částečně podporována, ale úplné parsování zatím není dokončeno.
Načítá načtení souboru OBJ také .mtl materiál?
Ano, když ObjLoadOptions.enable_materials = True (výchozí). Knihovna hledá .mtl soubor ve stejném adresáři jako .obj soubor. Pokud .mtl chybí, geometrie je stále načtena a je vypsáno varování.
Mohu načíst soubor z proudu bajtů místo cesty?
Ano. scene.open() přijímá libovolný objekt podobný souboru s .read() metodou kromě řetězce s cestou k souboru. Předávejte otevřený binární stream (např., io.BytesIO) přímo. Scene.from_file() přijímá pouze řetězec s cestou k souboru.
Jak získám normály povrchu?
Po načtení zkontrolujte mesh.get_element(VertexElementType.NORMAL). Toto vrací VertexElementNormal její data seznam obsahuje jeden normálový vektor na referenci, mapovaný podle mapping_mode a reference_mode.
from aspose.threed.entities import Mesh, VertexElementType
normals = mesh.get_element(VertexElementType.NORMAL)
if normals:
print(normals.data[0]) # First normal vectorJe knihovna thread‑safe při načítání více souborů současně?
Každý Scene objekt je nezávislý. Načítání samostatných souborů do samostatných Scene instancí z oddělených vláken je bezpečné, pokud nesdílíte jediný Scene mezi vlákny bez externího zamykání.