Cum să încărcați modele 3D în Python
Aspose.3D FOSS pentru Python oferă un API simplu pentru deschiderea fișierelor 3D fără nicio dependență nativă. După încărcarea unui fișier într-un Scene obiect, poți parcurge ierarhia nodurilor și citi datele brute de geometrie pentru fiecare mesh din scenă.
Ghid pas cu pas
Pasul 1: Instalează pachetul
Instalează Aspose.3D FOSS de pe PyPI. Nu sunt necesare biblioteci de sistem suplimentare.
pip install aspose-3d-fossVersiuni Python suportate: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.
Pasul 2: Importă clasa Scene
Clasa Scene clasa este containerul de nivel superior pentru toate datele 3D. Importă‑o împreună cu orice clase de opțiuni de încărcare de care ai nevoie.
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptionsToate clasele publice se află sub aspose.threed sau sub-pachetele sale (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).
Pasul 3: Încarcă un fișier
Folosește metoda statică Scene.from_file() metodă pentru a deschide orice format suportat. Biblioteca detectează formatul automat din extensia fișierului.
##Automatic format detection
scene = Scene.from_file("model.obj")Alternativ, creează un Scene instanță și apelează open(); util când vrei să transmiți opțiuni de încărcare sau să gestionezi erorile explicit:
scene = Scene()
scene.open("model.obj")Ambele metode suportă fișiere OBJ, STL (binare și ASCII), glTF 2.0 / GLB, COLLADA (DAE) și 3MF.
Pasul 4: Parcurge nodurile Scene
O scenă încărcată este un arbore de Node obiecte cu rădăcina în scene.root_node. Iterați recursiv pentru a găsi toate nodurile:
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)Fiecare Node poate transporta zero sau mai multe Entity obiecte (meshes, cameras, lights). Verificați node.entities pentru a vedea ce este atașat.
Pasul 5: Accesarea datelor de vârf și poligon
Convertiți entitatea unui nod la Mesh și citiți punctele sale de control (vertex positions) și poligoanele (face index lists):
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 este o listă de Vector4 obiecte; x, y, z poartă poziția și w este coordonata omogenă (în mod normal 1.0).
mesh.polygons este o listă de liste de întregi, în care fiecare listă internă este setul ordonat de indici ai punctelor de control pentru o față.
Pasul 6: Aplicarea opțiunilor de încărcare specifice formatului
Pentru un control detaliat asupra modului în care este interpretat un fișier OBJ, transmiteți un ObjLoadOptions instanță către 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)Pentru fișiere STL, clasa echivalentă este StlLoadOptions. Pentru glTF, utilizați GltfLoadOptions. Consultați referința API pentru o listă completă.
Probleme comune și soluții
FileNotFoundError la apelarea Scene.from_file()
Calea trebuie să fie absolută sau corectă relativ la directorul de lucru la rulare. Utilizați pathlib.Path pentru a construi căi fiabile:
from pathlib import Path
from aspose.threed import Scene
path = Path(__file__).parent / "assets" / "model.obj"
scene = Scene.from_file(str(path))mesh.polygons este gol după încărcarea unui fișier STL
Fișierele STL stochează triunghiurile ca fațete brute, nu ca o rețea indexată. După încărcare, poligoanele sunt sintetizate din acele fațete. Dacă polygons pare gol, verificați len(mesh.control_points); dacă numărul este un multiplu de 3, geometria este stocată în formă neindexată și fiecare triplet consecutiv de vârfuri formează un triunghi.
Neconcordanță a sistemului de coordonate (modelul pare rotit sau oglindit)
Instrumente diferite folosesc convenții diferite (Y-up vs Z-up, left-hand vs right-hand). Setați ObjLoadOptions.flip_coordinate_system = True sau aplicați o rotație la nodul rădăcină Transform după încărcare.
AttributeError: 'NoneType' object has no attribute 'polygons'
Lista de entități a unui nod poate conține entități non-rețea (camere, lumini). Întotdeauna verificați cu isinstance(entity, Mesh) înainte de a face casting.
Întrebări frecvente (FAQ)
Ce formate 3D pot încărca?
OBJ (Wavefront), STL (binare și ASCII), glTF 2.0 / GLB, COLLADA (DAE) și 3MF. Tokenizarea fișierelor FBX este parțial suportată, dar parsarea completă nu este încă finalizată.
Încărcarea unui fișier OBJ încarcă și .mtl materialul?
Da, când ObjLoadOptions.enable_materials = True (implicit). Biblioteca caută .mtl fișier în același director cu .obj fișier. Dacă .mtl lipsește, geometria este încărcată și se emite un avertisment.
Pot încărca un fișier dintr-un flux de octeți în loc de o cale?
Da. scene.open() acceptă orice obiect asemănător unui fișier cu un .read() metodă pe lângă un șir de cale de fișier. Transmite un flux binar deschis (de exemplu,., io.BytesIO) direct. Scene.from_file() acceptă doar un șir de cale de fișier.
Cum pot obține normele de suprafață?
După încărcare, verificați mesh.get_element(VertexElementType.NORMAL). Aceasta returnează un VertexElementNormal al cărui data lista conține un vector normal pentru fiecare referință, mapat conform 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 vectorEste biblioteca thread-safe pentru încărcarea simultană a mai multor fișiere?
Fiecare Scene obiect este independent. Încărcarea fișierelor separate în Scene instanțe din fire de execuție separate este sigură atâta timp cât nu partajați un singur Scene între firele de execuție fără blocare externă.