Jak načíst 3D modely v Python

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-foss

Podporované 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 ObjLoadOptions

Vš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 vector

Je 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í.

 Čeština