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-fossPodrž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 ObjLoadOptionsSve 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 vectorJe 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.