Hur man laddar 3D-modeller i Python
Aspose.3D FOSS för Python erbjuder ett enkelt API för att öppna 3D-filer utan några inhemska beroenden. Efter att ha laddat en fil i en Scene objekt kan du gå igenom nodhierarkin och läsa rå geometridata för varje mesh i scenen.
Steg-för-steg-guide
Steg 1: Installera paketet
Installera Aspose.3D FOSS från PyPI. Inga ytterligare systembibliotek krävs.
pip install aspose-3d-fossStödda Python-versioner: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.
Steg 2: Importera Scene-klassen
Den Scene klass är den översta behållaren för all 3D-data. Importera den tillsammans med eventuella laddningsalternativsklasser du behöver.
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptionsAlla offentliga klasser finns under aspose.threed eller dess underpaket (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).
Steg 3: Ladda en fil
Använd den statiska Scene.from_file() metoden för att öppna vilket stödformat som helst. Biblioteket upptäcker formatet automatiskt från filändelsen.
##Automatic format detection
scene = Scene.from_file("model.obj")Alternativt, skapa en Scene instans och anropa open(); användbart när du vill skicka laddningsalternativ eller hantera fel explicit:
scene = Scene()
scene.open("model.obj")Båda metoderna stödjer OBJ, STL (binär och ASCII), glTF 2.0 / GLB, COLLADA (DAE) och 3MF-filer.
Steg 4: Traversera scen-noder
En laddad scen är ett träd av Node objekt rotade vid scene.root_node. Iterera rekursivt för att hitta alla 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)Varje Node kan bära noll eller fler Entity objekt (meshes, kameror, ljus). Kontrollera node.entities för att se vad som är anslutet.
Steg 5: Åtkomst till vertex- och polygondata
Casta en nods entitet till Mesh och läs dess kontrollpunkter (vertex positions) och 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 är en lista med Vector4 objekt; x, y, z bär positionen och w är den homogena koordinaten (vanligtvis 1.0).
mesh.polygons är en lista med listor av heltal, där varje inre lista är den ordnade uppsättningen av kontrollpunktsindex för ett ansikte.
Steg 6: Tillämpa format‑specifika laddningsalternativ
För finjusterad kontroll över hur en OBJ-fil tolkas, skicka en ObjLoadOptions instans till 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)För STL-filer är den motsvarande klassen StlLoadOptions. För glTF, använd GltfLoadOptions. Se API-referens för en fullständig lista.
Vanliga problem och lösningar
FileNotFoundError vid anrop av Scene.from_file()
Sökvägen måste vara absolut eller korrekt relativ till arbetskatalogen vid körning. Använd pathlib.Path för att bygga pålitliga sökvägar:
from pathlib import Path
from aspose.threed import Scene
path = Path(__file__).parent / "assets" / "model.obj"
scene = Scene.from_file(str(path))mesh.polygons är tom efter att ha läst in en STL-fil
STL-filer lagrar trianglar som råa facetter, inte ett indexerat nät. Efter inläsning syntetiseras polygoner från dessa facetter. Om polygons verkar tom, kontrollera len(mesh.control_points); om antalet är en multipel av 3 är geometrin lagrad i oindexerad form och varje på varandra följande trippel av vertexer bildar en triangel.
Mismatch i koordinatsystem (modellen verkar roterad eller spegelvänd)
Olika verktyg använder olika konventioner (Y-upp vs Z-upp, vänsterhand vs högerhand). Ställ in ObjLoadOptions.flip_coordinate_system = True eller applicera en rotation på rotnodens Transform efter inläsning.
AttributeError: 'NoneType' object has no attribute 'polygons'
En nods entitetslista kan innehålla icke-mesh‑entiteter (kameror, ljus). Säkerställ alltid med isinstance(entity, Mesh) innan du castar.
Vanliga frågor (FAQ)
Vilka 3D-format kan jag läsa in?
OBJ (Wavefront), STL (binär och ASCII), glTF 2.0 / GLB, COLLADA (DAE) och 3MF. FBX‑filens tokenisering stöds delvis men fullständig parsning är ännu inte klar.
Laddar inläsning av en OBJ‑fil även .mtl materialet?
Ja, när ObjLoadOptions.enable_materials = True (standard). Biblioteket söker efter .mtl fil i samma katalog som .obj fil. Om .mtl saknas, laddas geometrin fortfarande och en varning ges ut.
Kan jag läsa in en fil från en byte‑ström istället för en sökväg?
Ja. scene.open() accepterar vilket fil‑liknande objekt som helst med en .read() metod utöver en filsökvägssträng. Skicka en öppen binärström (t.ex., io.BytesIO) direkt. Scene.from_file() accepterar endast en filsökvägssträng.
Hur får jag ytnormaler?
Efter inläsning, kontrollera mesh.get_element(VertexElementType.NORMAL). Detta returnerar en VertexElementNormal vars data lista innehåller en normalvektor per referens, mappad enligt mapping_mode och reference_mode.
from aspose.threed.entities import Mesh, VertexElementType
normals = mesh.get_element(VertexElementType.NORMAL)
if normals:
print(normals.data[0]) # First normal vectorÄr biblioteket trådsäkert för att ladda flera filer samtidigt?
Varje Scene objektet är oberoende. Att ladda separata filer i separata Scene instanser från separata trådar är säkert så länge du inte delar en enda Scene över trådar utan extern låsning.