Ako načítať 3D modely v Python

Ako načítať 3D modely v Python

Aspose.3D FOSS pre Python poskytuje jednoduché API na otváranie 3D súborov bez akýchkoľvek natívnych závislostí. Po načítaní súboru do Scene objektu môžete prechádzať hierarchiu uzlov a čítať surové geometrické dáta pre každú sieť v scéne.

Postupný návod

Krok 1: Nainštalujte balík

Nainštalujte Aspose.3D FOSS z PyPI. Nie sú potrebné žiadne ďalšie systémové knižnice.

pip install aspose-3d-foss

Podporované verzie Python: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.


Krok 2: Importujte triedu Scene

Trieda Scene je kontajner najvyššej úrovne pre všetky 3D dáta. Importujte ju spolu s akýmikoľvek triedami pre možnosti načítania, ktoré potrebujete.

from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions

Všetky verejné triedy sa nachádzajú pod aspose.threed alebo v jej podbalíčkoch (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).


Krok 3: Načítajte súbor

Použite statickú Scene.from_file() metódu na otvorenie akéhokoľvek podporovaného formátu. Knižnica automaticky detekuje formát podľa prípony súboru.

##Automatic format detection
scene = Scene.from_file("model.obj")

Alternatívne vytvorte Scene inštanciu a zavolajte open(); užitočné, keď chcete explicitne odovzdať možnosti načítania alebo spracovať chyby:

scene = Scene()
scene.open("model.obj")

Obe metódy podporujú súbory OBJ, STL (binárny a ASCII), glTF 2.0 / GLB, COLLADA (DAE) a 3MF.


Krok 4: Prechádzajte uzly scény

Načítaná scéna je strom objektov Node zakorenených v scene.root_node. Prechádzajte rekurzívne, aby ste našli všetky 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 niesť nula alebo viac Entity objekty (meshes, kamery, svetlá). Skontrolujte node.entities aby ste videli, čo je pripojené.


Krok 5: Prístup k dátam vrcholov a polygonov

Pretypujte entitu uzla na Mesh a prečítajte jej kontrolné body (pozície vrcholov) a polygóny (zoznamy indexov tvárí):

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 zoznamom Vector4 objektov; x, y, z nesú pozíciu a w je homogénna súradnica (zvyčajne 1.0).

mesh.polygons je zoznam zoznamov celých čísel, kde každý vnútorný zoznam je usporiadaná množina indexov kontrolných bodov pre jednu plochu.


Krok 6: Použitie formátovo špecifických možností načítania

Pre detailnú kontrolu nad tým, ako sa interpretuje súbor OBJ, odovzdajte ObjLoadOptions inštanciu 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)

Pre súbory STL je ekvivalentná trieda StlLoadOptions. Pre glTF použite GltfLoadOptions. Pozrite si referenciu API pre úplný zoznam.


Bežné problémy a riešenia

FileNotFoundError pri volaní Scene.from_file()

Cesta musí byť absolútna alebo správne relatívna k pracovnému adresáru v čase behu. Použite pathlib.Path na vytvorenie spoľahlivých ciest:

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ázdny po načítaní súboru STL

STL súbory ukladajú trojuholníky ako surové fasety, nie ako indexovanú sieť. Po načítaní sa polygóny syntetizujú z týchto fasiet. Ak polygons vyzerá prázdny, skontrolujte len(mesh.control_points); ak je počet násobkom 3, geometria je uložená v neindexovanej forme a každá po sebe nasledujúca trojica vrcholov tvorí jeden trojuholník.

Nesúlad súradnicového systému (model sa javí otočený alebo zrkadlený)

Rôzne nástroje používajú rôzne konvencie (Y-up vs Z-up, ľavá ruka vs pravá ruka). Nastavte ObjLoadOptions.flip_coordinate_system = True alebo aplikovať rotáciu na koreňového uzla Transform po načítaní.

AttributeError: 'NoneType' object has no attribute 'polygons'

Zoznam entít uzla môže obsahovať ne‑mesh entity (kamery, svetlá). Vždy chráňte pomocou isinstance(entity, Mesh) pred pretypovaním.


Často kladené otázky (FAQ)

Ktoré 3D formáty môžem načítať?

OBJ (Wavefront), STL (binárny a ASCII), glTF 2.0 / GLB, COLLADA (DAE) a 3MF. Tokenizácia FBX súborov je čiastočne podporovaná, ale úplné parsovanie ešte nie je dokončené.

Načíta sa pri načítaní OBJ súboru aj .mtl materiál?

Áno, keď ObjLoadOptions.enable_materials = True (predvolené). Knižnica hľadá .mtl súbor v rovnakom adresári ako .obj súbor. Ak .mtl chýba, geometria sa stále načíta a je vydané varovanie.

Môžem načítať súbor z bajtového prúdu namiesto cesty?

Áno. scene.open() akceptuje akýkoľvek objekt podobný súboru s .read() metódou okrem reťazca cesty k súboru. Odovzdajte otvorený binárny prúd (napr., io.BytesIO) priamo. Scene.from_file() akceptuje iba reťazec cesty k súboru.

Ako získam normály povrchu?

Po načítaní skontrolujte mesh.get_element(VertexElementType.NORMAL). Toto vracia VertexElementNormal ktorého data zoznam obsahuje jeden normálny vektor na referenciu, mapovaný podľa 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 knižnica vláknovo bezpečná pri načítavaní viacerých súborov súčasne?

Každý Scene objekt je nezávislý. Načítanie samostatných súborov do samostatných Scene inštancie z oddelených vlákien je bezpečné pokiaľ nesdielate jediný Scene naprieč vláknami bez externého zamykania.

 Slovenčina