Kako učitati 3D modele u Python

Kako učitati 3D modele u Python

Aspose.3D FOSS za Python pruža jednostavno API za otvaranje 3D datoteka bez ikakvih izvornih ovisnosti. Nakon učitavanja datoteke u Scene objekt, možete proći hijerarhiju čvorova i pročitati sirove geometrijske podatke za svaki mesh u sceni.

Vodič korak po korak

Korak 1: Instalirajte paket

Instalirajte Aspose.3D FOSS s PyPI-a. Nisu potrebne dodatne sistemske biblioteke.

pip install aspose-3d-foss

Podržane Python verzije: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.


Korak 2: Uvezite klasu Scene

Klasa Scene je kontejner najviše razine za sve 3D podatke. Uvezite je zajedno sa svim klasama opcija učitavanja koje su vam potrebne.

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

Sve javne klase nalaze se pod aspose.threed ili njegovim podpaketima (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).


Korak 3: Učitajte datoteku

Koristite statičku Scene.from_file() metodu za otvaranje bilo kojeg podržanog formata. Biblioteka automatski otkriva format iz ekstenzije datoteke.

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

Alternativno, stvorite Scene instancu i pozovite open(); korisno kada želite proslijediti opcije učitavanja ili izričito rukovati greškama:

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

Obje metode podržavaju OBJ, STL (binarni i ASCII), glTF 2.0 / GLB, COLLADA (DAE) i 3MF datoteke.


Korak 4: Prođite kroz čvorove scene

Učitana scena je stablo od Node objekata s korijenom u scene.root_node. Iterirajte rekurzivno kako biste pronašli sve čvorove:

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)

Svaki Node može nositi nula ili više Entity objekte (mreže, kamere, svjetla). Provjeri node.entities da vidiš što je pričvršćeno.


Korak 5: Pristup podacima o vrhovima i poligonima

Pretvori entitet čvora u Mesh i pročitaj njegove kontrolne točke (pozicije vrhova) i poligone (liste indeksa površina):

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 popis Vector4 objekata; x, y, z nose položaj i w je homogen koordinata (obično 1.0).

mesh.polygons je popis popisa cijelih brojeva, gdje je svaki unutarnji popis uređen skup indeksa kontrolnih točaka za jedno lice.


Korak 6: Primijenite formatno-specifične opcije učitavanja

Za finu kontrolu nad načinom interpretacije OBJ datoteke, proslijedite ObjLoadOptions instancu 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)

Za STL datoteke, ekvivalentna klasa je StlLoadOptions. Za glTF, koristite GltfLoadOptions. Pogledajte API referencu za potpuni popis.


Uobičajeni problemi i rješenja

FileNotFoundError pri pozivu Scene.from_file()

Putanja mora biti apsolutna ili ispravna relativno na radni direktorij u vrijeme izvođenja. Koristite pathlib.Path za izgradnju pouzdanih putanja:

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 prazan nakon učitavanja STL datoteke

STL datoteke pohranjuju trokute kao sirove fasete, a ne indeksiranu mrežu. Nakon učitavanja, poligoni se sintetiziraju iz tih faseta. Ako polygons se pojavljuje prazno, provjerite len(mesh.control_points); ako je broj višekratnik od 3, geometrija je pohranjena u neindeksiranom obliku i svaki uzastopni trojac vrhova tvori jedan trokut.

Neusklađenost koordinatnog sustava (model se čini rotiranim ili zrcalnim)

Različiti alati koriste različite konvencije (Y-gore vs Z-gore, lijeva ruka vs desna ruka). Postavite ObjLoadOptions.flip_coordinate_system = True ili primijenite rotaciju na korijenski čvor Transform nakon učitavanja.

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

Popis entiteta čvora može sadržavati entitete koji nisu mreže (kamere, svjetla). Uvijek provjerite s isinstance(entity, Mesh) prije pretvaranja.


Često postavljana pitanja (FAQ)

Koje 3D formate mogu učitati?

OBJ (Wavefront), STL (binarni i ASCII), glTF 2.0 / GLB, COLLADA (DAE) i 3MF. Tokenizacija FBX datoteka je djelomično podržana, ali potpuna obrada još nije dovršena.

Učita li učitavanje OBJ datoteke i .mtl materijal?

Da, kada ObjLoadOptions.enable_materials = True (zadano). Biblioteka traži .mtl datoteku u istom direktoriju kao .obj datoteka. Ako je .mtl nedostaje, geometrija se i dalje učitava i ispisuje se upozorenje.

Mogu li učitati datoteku iz bajt streama umjesto iz putanje?

Da. scene.open() prihvaća bilo koji objekt sličan datoteci koji ima .read() metodu uz string putanje datoteke. Proslijedite otvoreni binarni tok (npr., io.BytesIO) izravno. Scene.from_file() prihvaća samo string putanje datoteke.

Kako dobiti površinske normale?

Nakon učitavanja, provjerite mesh.get_element(VertexElementType.NORMAL). Ovo vraća VertexElementNormal čiji data lista sadrži jedan normalni vektor po referenci, mapiran prema mapping_mode i 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 li biblioteka thread‑safe za učitavanje više datoteka istovremeno?

Svaki Scene objekt je neovisan. Učitavanje odvojenih datoteka u odvojene Scene instance iz odvojenih niti je sigurno sve dok ne dijelite jednu Scene među nitima bez vanjskog zaključavanja.

 Hrvatski