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 indlæsning af en fil i en 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
Den Scene klasse er den øverste container for al 3D-data. Importer den sammen med eventuelle load-option klasser, du har brug for.
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptionsAlle offentlige klasser findes under aspose.threed eller dens 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 opdager 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 load options 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: Gå igennem scenenoder
En indlæst scene er et træ af Node objekter med roden 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, kameraer, lys). Tjek node.entities for at se, hvad der er vedhæftet.
Trin 5: Få adgang til vertex- og polygondata
Cast nodeens 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 det ordnede sæt af kontrolpunkt‑indekser for én flade.
Trin 6: Anvend format‑specifikke load‑options
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, brug GltfLoadOptions. Se API‑reference for en komplet liste.
Almindelige problemer og løsninger
FileNotFoundError ved kald af Scene.from_file()
Stien skal være absolut eller korrekt relativ i forhold til arbejdsbiblioteket 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 ser ud til at være tom, 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-mismatch (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 anvende 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 du caster.
Ofte stillede spørgsmål (FAQ)
Hvilke 3D-formater kan jeg indlæse?
OBJ (Wavefront), STL (binær og ASCII), glTF 2.0 / GLB, COLLADA (DAE) og 3MF. FBX‑fil‑tokenisering understøttes delvist, men fuld parsing er endnu ikke færdig.
Indlæser indlæsning af en OBJ-fil også .mtl materiale?
Ja, når ObjLoadOptions.enable_materials = True (standardindstillingen). Biblioteket søger efter .mtl fil i samme mappe som .obj fil. Hvis .mtl mangler, indlæses geometrien stadig, og en advarsel udstedes.
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 filstistring. Overgiv en åben binær strøm (f.eks., io.BytesIO) direkte. Scene.from_file() accepterer kun en filstistring.
Hvordan får jeg overfladenormaller?
Efter indlæsning, tjek mesh.get_element(VertexElementType.NORMAL). Dette returnerer en VertexElementNormal hvis data listen 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?
Hver Scene objekt er uafhængig. Indlæsning af separate filer i separate Scene instanser fra separate tråde er sikkert så længe du ikke deler en enkelt Scene på tværs af tråde uden ekstern låsning.