Kaip įkelti 3D modelius į Python
Aspose.3D FOSS for Python suteikia paprastą API 3D failų atvėrimui be jokių natūralių priklausomybių. Įkėlus failą į Scene objektą, galite vaikščioti po mazgų hierarchiją ir skaityti neapdorotus geometrijos duomenis kiekvienam tinklui (mesh) scenoje.
Žingsnis po žingsnio vadovas
Žingsnis 1: Įdiekite paketą
Įdiekite Aspose.3D FOSS iš PyPI. Papildomos sistemos bibliotekos nereikalingos.
pip install aspose-3d-fossPalaikomos Python versijos: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.
Žingsnis 2: Importuokite Scene klasę
Ši 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šos klasės yra po aspose.threed arba jos subpaketais (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).
Žingsnis 3: Įkelkite failą
Naudokite statinį Scene.from_file() metodą, kad atvertumėte bet kurį palaikomą formatą. Biblioteka automatiškai aptinka formatą pagal failo plėtinį.
##Automatic format detection
scene = Scene.from_file("model.obj")Alternatyviai, sukurkite Scene instanciją ir iškvieskite open(); 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šykite Scene mazgus
Įkelta scena yra medžio struktūra iš Node objektų, kurių šaknys yra scene.root_node. Iteruokite rekursyviai, 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 objektus (tinklus, kameras, šviesas). Patikrinkite node.entities norėdami pamatyti, kas prijungta.
Žingsnis 5: Prieiga prie viršūnių ir daugiakampių duomenų
Konvertuokite mazgo objektą į Mesh ir perskaitykite jo kontrolinius 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 sąrašas Vector4 objektų; 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ų, kur kiekvienas vidinis sąrašas yra tvarkingas kontrolinių taškų indeksų rinkinys vienam paviršiui.
Žingsnis 6: Taikyti formatui specifines įkėlimo parinktis
Norint gauti smulkią kontrolę, kaip interpretuojamas OBJ failas, perduokite ObjLoadOptions instance į 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. Žr. API nuorodą pilnam sąrašui.
Dažnos problemos ir sprendimai
FileNotFoundError iškviečiant Scene.from_file()
Kelias turi būti absoliutus arba teisingas, atsižvelgiant į darbinį katalogą vykdymo metu. Naudokite pathlib.Path kurti patikimus kelius:
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 įkėlus STL failą
STL failai saugo trikampius kaip neapdorotas plokštumas, o ne indeksuotą tinklą. Įkėlę, poligonai sintezuojami iš tų plokštumų. Jei polygons atrodo tuščias, patikrinkite len(mesh.control_points); jei skaičius yra 3 kartotinis, geometrija saugoma neindeksuota forma ir kiekviena nuosekli 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 vs Z‑aukštyje, kairės rankos vs dešinės rankos). Nustatykite ObjLoadOptions.flip_coordinate_system = True arba pritaikyti sukimosi transformaciją šaknies mazgo Transform po įkėlimo.
AttributeError: 'NoneType' object has no attribute 'polygons'
Mazgo objektų sąraše gali būti ne tinklo objektų (kameros, šviesos). Visada apsaugokite su isinstance(entity, Mesh) prieš konvertavimą.
Dažnai užduodami klausimai (DUK)
Kuriuos 3D formatus galiu įkelti?
OBJ (Wavefront), STL (binarinis ir 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 (numatyta). Biblioteka ieško .mtl failo toje pačioje kataloge, kur .obj failas. Jei .mtl trūksta, geometrija vis tiek įkeliamas ir išduodamas įspėjimas.
Ar galiu įkelti failą iš baitų srauto, o ne iš kelio?
Taip. scene.open() priima bet kokį failui panašų objektą su .read() metodu, be failo kelio eilutės. Perduokite atvertą binarinį srautą (pvz., io.BytesIO) tiesiogiai. Scene.from_file() priima tik failo kelio eilutę.
Kaip gauti paviršiaus normalės?
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 thread-safe, kai keli failai įkeliami lygiagrečiai?
Kiekvienas Scene objektas yra nepriklausomas. Įkeliant atskirus failus į atskirus Scene instancijos iš atskirų gijų yra saugios, kol nesidalinate vienos Scene tarp gijų be išorinio užrakinimo.