Kaip įkelti 3D modelius Python kalboje
Aspose.3D FOSS for Python suteikia paprastą API 3D failų atvėrimui be jokių natūralių priklausomybių. Įkėlę failą į Scene objektą, galite naršyti mazgų hierarchiją ir skaityti neapdorotus geometrijos duomenis kiekvienam mesh scenoje.
Žingsnis po žingsnio vadovas
Žingsnis 1: įdiekite paketą
Įdiekite Aspose.3D FOSS iš PyPI. Papildomų sistemų bibliotekų nereikia.
pip install aspose-3d-fossPalaikomos Python versijos: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.
Žingsnis 2: Importuokite scenos klasę
Scene klasė yra aukščiausio lygio konteineris visiems 3D duomenims. Importuokite ją kartu su visomis reikalingomis įkėlimo parinkčių klasėmis.
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptionsVisos viešosios klasės yra po aspose.threed arba jos subpaketuose (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).
Žingsnis 3: Įkelti failą
Naudokite statinį Scene.from_file() metodą, kad atidarytumėte bet kurį palaikomą formatą. Biblioteka automatiškai nustato formatą pagal failo plėtinį.
##Automatic format detection
scene = Scene.from_file("model.obj")Alternatyviai sukurkite Scene egzempliorių ir iškvieskite open(); tai naudinga, kai norite perduoti įkėlimo parinktis arba išreikštinai tvarkyti klaidas:
scene = Scene()
scene.open("model.obj")Abu metodai palaiko OBJ, STL (binarią ir ASCII), glTF 2.0 / GLB, COLLADA (DAE) ir 3MF failus.
Žingsnis 4: Naršyti scenos mazgus
Įkelta scena yra Node objektų medis, kurio šaknis yra scene.root_node. Rekursyviai iteruokite, kad rastumėte visus mazgus:
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)Kiekvienas Node gali turėti nulį arba daugiau Entity objektų (tinklus, kameras, šviesas). Patikrinkite node.entities, kad pamatytumėte, kas prijungta.
Žingsnis 5: Prieiga prie viršūnių ir daugiakampių duomenų
Konvertuokite mazgo objektą į Mesh ir perskaitykite jo valdymo taškus (viršūnių pozicijas) ir daugiakampius (veido indekso sąrašus):
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 yra Vector4 objektų sąrašas; x, y, z nurodo padėtį ir w yra homogeniška koordinatė (paprastai 1.0).
mesh.polygons yra sąrašas sąrašų sveikųjų skaičių, kuriame kiekvienas vidinis sąrašas yra išrikiuota kontrolinių taškų indeksų aibė vienam veidui.
Žingsnis 6: taikyti formatui specifines įkėlimo parinktis
Norėdami smulkią kontrolę, kaip interpretuojamas OBJ failas, perduokite ObjLoadOptions egzempliorių į 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)STL failams atitinkama klasė yra StlLoadOptions. glTF atveju naudokite GltfLoadOptions. Žiūrėkite API reference pilnam sąrašui.
Įprastos problemos ir sprendimai
FileNotFoundError kviestant Scene.from_file()
Kelias turi būti absoliutus arba teisingas santykinis, atsižvelgiant į darbinį katalogą vykdymo metu. Naudokite pathlib.Path patikimiems keliams kurti:
from pathlib import Path
from aspose.threed import Scene
path = Path(__file__).parent / "assets" / "model.obj"
scene = Scene.from_file(str(path))mesh.polygons yra tuščias po STL failo įkėlimo
STL failai saugo trikampius kaip neapdorotas plokštumas, o ne indeksuotą tinklą. Įkėlę, daugiakampiai sintezuojami iš tų plokštumų. Jei polygons yra tuščias, patikrinkite len(mesh.control_points); jei skaičius yra 3 kartų kartotinis, geometrija saugoma neindeksuota forma ir kiekviena nuosekliai einanti trijų viršūnių grupė sudaro vieną trikampį.
Koordinačių sistemos nesutapimas (modelis atrodo pasukęs arba veidrodinis)
Skirtingi įrankiai naudoja skirtingas konvencijas (Y‑aukštyje prieš Z‑aukštyje, kairės rankos prieš dešinės rankos). Nustatykite ObjLoadOptions.flip_coordinate_system = True arba pritaikykite sukimosi kampą šaknies mazgo Transform po įkėlimo.
AttributeError: 'NoneType' object has no attribute 'polygons'
Mazgo entiteto sąraše gali būti ne‑mesh entitetų (kamerų, šviesų). Visada naudokite isinstance(entity, Mesh) apsaugą prieš konvertavimą.
Dažnai užduodami klausimai (DUK)
Kuriuos 3D formatus galiu įkelti?
OBJ (Wavefront), STL (binary and ASCII), glTF 2.0 / GLB, COLLADA (DAE) ir 3MF. FBX failų tokenizavimas yra dalinai palaikomas, tačiau pilnas analizavimas dar nebaigtas.
Ar įkeliant OBJ failą taip pat įkeliamas .mtl medžiaga?
Taip, kai ObjLoadOptions.enable_materials = True (numatytasis). Biblioteka ieško .mtl failo toje pačioje kataloge kaip ir .obj failas. Jei .mtl trūksta, geometrija vis tiek įkeliamas ir išduodamas įspėjimas.
Ar galiu įkelti failą iš baitų srauto vietoj kelio?
Taip. scene.open() priima bet kokį failo tipo objektą su .read() metodu, be to, failo kelio eilutę. Perduokite atvirą binarinį srautą (pvz., io.BytesIO) tiesiogiai. Scene.from_file() priima tik failo kelio eilutę.
Kaip gauti paviršiaus normales?
Po įkėlimo patikrinkite mesh.get_element(VertexElementType.NORMAL). Tai grąžina VertexElementNormal, kurio data sąraše yra po vieną normalų vektorių kiekvienai nuorodai, susietą pagal mapping_mode ir reference_mode.
from aspose.threed.entities import Mesh, VertexElementType
normals = mesh.get_element(VertexElementType.NORMAL)
if normals:
print(normals.data[0]) # First normal vectorAr biblioteka yra gijų saugi (thread‑safe) kelių failų įkėlimui vienu metu?
Kiekvienas Scene objektas yra nepriklausomas. Atskirų failų įkėlimas į atskirus Scene egzempliorius iš atskirų gijų yra saugus, jei nesidalinate vieno Scene tarp gijų be išorinio užrakinimo.