Sådan indlæses 3D-modeller i Python
Aspose.3D FOSS for Python leverer et enkelt API til at åbne 3D-filer uden nogen native afhængigheder. Efter at have indlæst en fil i et Scene-objekt, kan du traversere nodehierarkiet og læse rå geometridata for hver mesh i scenen.
Trin-for-trin guide
Trin 1: Installer pakken
Installer Aspose.3D FOSS fra PyPI. Ingen yderligere systembiblioteker er påkrævet.
pip install aspose-3d-fossUnderstøttede Python-versioner: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.
Trin 2: Importer Scene‑klassen
Klassen Scene er den øverste container for alle 3D‑data. Importer den sammen med eventuelle indlæsningsindstillingsklasser, du har brug for.
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptionsAlle offentlige klasser findes under aspose.threed eller dets underpakker (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).
Trin 3: Indlæs en fil
Brug den statiske Scene.from_file()‑metode til at åbne ethvert understøttet format. Biblioteket registrerer formatet automatisk ud fra filendelsen.
##Automatic format detection
scene = Scene.from_file("model.obj")Alternativt kan du oprette en Scene‑instans og kalde open(); nyttigt, når du vil videregive indlæsningsindstillinger eller håndtere fejl eksplicit:
scene = Scene()
scene.open("model.obj")Begge metoder understøtter OBJ, STL (binær og ASCII), glTF 2.0 / GLB, COLLADA (DAE) og 3MF-filer.
Trin 4: Gennemløb scenenoder
En indlæst scene er et træ af Node‑objekter med rod i scene.root_node. Iterer rekursivt for at finde alle noder:
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)Hver Node kan bære nul eller flere Entity-objekter (meshes, cameras, lights). Tjek node.entities for at se, hvad der er vedhæftet.
Trin 5: Få adgang til Vertex- og polygondata
Kast en nodes enhed til Mesh og læs dens kontrolpunkter (vertex positions) og polygoner (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 er en liste over Vector4-objekter; x, y, z bærer positionen og w er den homogene koordinat (normalt 1.0).
mesh.polygons er en liste af lister af heltal, hvor hver indre liste er den ordnede mængde af kontrolpunktindekser for én flade.
Trin 6: Anvend format‑specifikke indlæsningsindstillinger
For finjusteret kontrol over, hvordan en OBJ‑fil fortolkes, skal du videregive en ObjLoadOptions‑instans til 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)For STL-filer er den tilsvarende klasse StlLoadOptions. For glTF skal du bruge GltfLoadOptions. Se API-referencen for en komplet liste.
Almindelige problemer og rettelser
FileNotFoundError ved kald af Scene.from_file()
Stien skal være absolut eller korrekt relativ til arbejdsmappe ved kørsel. Brug pathlib.Path til at opbygge pålidelige stier:
from pathlib import Path
from aspose.threed import Scene
path = Path(__file__).parent / "assets" / "model.obj"
scene = Scene.from_file(str(path))mesh.polygons er tom efter indlæsning af en STL-fil
STL-filer gemmer trekanter som rå facetter, ikke som et indekseret net. Efter indlæsning syntetiseres polygoner fra disse facetter. Hvis polygons fremstår tom, så tjek len(mesh.control_points); hvis antallet er et multiplum af 3, er geometrien gemt i uindekseret form, og hver på hinanden følgende tredobling af vertexer udgør en trekant.
Koordinatsystem uoverensstemmelse (model ser roteret eller spejlet ud)
Forskellige værktøjer bruger forskellige konventioner (Y‑op vs Z‑op, venstre‑hånd vs højre‑hånd). Indstil ObjLoadOptions.flip_coordinate_system = True eller anvend en rotation på rotnodens Transform efter indlæsning.
AttributeError: 'NoneType' object has no attribute 'polygons'
En nodes entitetsliste kan indeholde ikke‑mesh‑entiteter (kameraer, lys). Beskyt altid med isinstance(entity, Mesh) før casting.
Ofte stillede spørgsmål (FAQ)
Hvilke 3D‑formater kan jeg indlæse?
OBJ (Wavefront), STL (binary and ASCII), glTF 2.0 / GLB, COLLADA (DAE) og 3MF. FBX-fil-tokenisering understøttes delvist, men fuld parsing er endnu ikke fuldført.
Indlæser en OBJ-fil også materialet .mtl?
Ja, når ObjLoadOptions.enable_materials = True (standard). Biblioteket søger efter .mtl-filen i samme mappe som .obj-filen. Hvis .mtl mangler, indlæses geometrien stadig, og der udstedes en advarsel.
Kan jeg indlæse en fil fra en byte‑strøm i stedet for en sti?
Ja. scene.open() accepterer ethvert fil‑lignende objekt med en .read()‑metode ud over en filsti som streng. Overfør en åben binær strøm (f.eks., io.BytesIO) direkte. Scene.from_file() accepterer kun en filsti som streng.
Hvordan får jeg overfladenormaler?
Efter indlæsning, tjek mesh.get_element(VertexElementType.NORMAL). Dette returnerer en VertexElementNormal, hvis data-liste indeholder én normalvektor pr. reference, kortlagt i henhold til mapping_mode og reference_mode.
from aspose.threed.entities import Mesh, VertexElementType
normals = mesh.get_element(VertexElementType.NORMAL)
if normals:
print(normals.data[0]) # First normal vectorEr biblioteket trådsikkert ved indlæsning af flere filer samtidigt?
Hvert Scene-objekt er uafhængigt. Indlæsning af separate filer i separate Scene-instanser fra separate tråde er sikkert, så længe du ikke deler et enkelt Scene på tværs af tråde uden ekstern låsning.