Wie man 3D-Modelle in Python lädt

Wie man 3D-Modelle in Python lädt

Aspose.3D FOSS für Python bietet eine einfache API zum Öffnen von 3D-Dateien ohne natürliche Abhängigkeiten. Nach dem Laden einer Datei in ein Scene Objekt, können Sie die Knotenhierarchie gehen und lesen Rohgeometrie Daten für jedes Netz in der Szene.

Schritt für Schritte

Schritt 1: Installieren des Pakets

Installieren Sie Aspose.3D FOSS von PyPI. Keine zusätzlichen Systembibliotheken erforderlich.

asposefoss/3d is not yet published — build from source until it ships. See the project README for build instructions.

Unterstützte Python-Versionen: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.


Schritt 2: Importieren der Szenenklasse

Die Scene Importieren Sie es zusammen mit allen Ladeoptionsklassen, die Sie benötigen.

from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions

Die öffentlichen Klassen leben unter der aspose.threed oder deren Unterpakete (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).


Schritt 3: Laden einer Datei ein

Verwenden Sie die statische Scene.from_file() Die Bibliothek erkennt das Format automatisch aus der Dateierweiterung.

##Automatic format detection
scene = Scene.from_file("model.obj")

Die Kommission hat die Scene Anruf und Aufforderung open(); nützlich, wenn Sie die Ladeoptionen übergeben oder Fehler explizit behandeln möchten:

scene = Scene()
scene.open("model.obj")

Beide Methoden unterstützen OBJ-, STL- (binär und ASCII), glTF 2.0 / GLB, COLLADA (DAE) und 3MF-Dateien.


Schritt 4: Traverse-Szenenknoten

Eine geladene Szene ist ein Baum von Node Objekte, die auf der scene.root_node.Iterieren Sie rekursiv , um alle Knoten zu finden:

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)

Jeder von ihnen Node kann null oder mehr tragen Entity Gegenstände (Maschen, Kameras, Lichter). node.entities um zu sehen, was angebracht ist.


Schritt 5: Zugriff auf Vertex- und Polygondaten

Die Entität eines Knoten auf die Mesh und die Kontrollpunkte (Spitzenpositionen) und Polygone (Fassaden-Indexlisten) lesen:

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 ist eine Liste von Vector4 Gegenstände; x, y, z die Position zu halten und w ist die homogene Koordinate (normalerweise 1,0).

mesh.polygons ist eine Liste von ganzen Zahlen, wobei jede innere Liste die geordnete Menge der Kontrollpunktindizes für eine Fläche darstellt.


Schritt 6: Anwendungen für Format-spezifische Ladeoptionen

Für eine detaillierte Kontrolle der Interpretation einer OBJ-Datei, geben Sie einen ObjLoadOptions In diesem Fall 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-Dateien ist die entsprechende Klasse: StlLoadOptions.Für glTF: Verwenden GltfLoadOptions.- Sieh dir das an . Referenz zur API für eine vollständige Liste.


Häufige Probleme und Lösungen

FileNotFoundError beim Anrufen Scene.from_file()

Der Pfad muss zum Zeitpunkt der Ausführung absolut oder korrekt im Verhältnis zur Arbeitsmappe sein. pathlib.Path zuverlässige Wege aufzubauen:

from pathlib import Path
from aspose.threed import Scene

path = Path(__file__).parent / "assets" / "model.obj"
scene = Scene.from_file(str(path))

mesh.polygons ist nach dem Laden einer STL-Datei leer.

STL-Dateien speichern Dreiecken als Rohfacetten, nicht als ein indiziertes Netz. Nach dem Laden werden Polygone aus diesen Facetts synthetisiert. Wenn polygons Erscheint leer, überprüfen Sie len(mesh.control_points);Wenn die Zahl ein Vielfaches von 3 ist, wird die Geometrie in unindexierter Form gespeichert und jedes aufeinanderfolgende Dreifach-Gipfel bildet ein Dreieck.

Nicht übereinstimmende Koordinatensysteme (Modell wird gedreht oder spiegeln)

Verschiedene Werkzeuge verwenden verschiedene Konventionen (Y-up vs. Z- up, links/rechts). Setzen Sie die Daten auf der Seite des Gerätes und setzen Sie sie in den Schaltfeld. ObjLoadOptions.flip_coordinate_system = True oder eine Rotation auf den Wurzelknoten anwenden Transform nach dem Laden.

AttributeError: 'NoneType' object has no attribute 'polygons'

Die Entitätsliste eines Knotenpunkts kann nicht-mesch entitäten (Kameras, Lichter) enthalten. isinstance(entity, Mesh) Vor dem Casting.


Häufig gestellte Fragen (FAQ)

Welche 3D-Formate kann ich laden?

OBJ (Wavefront), STL (binär und ASCII), glTF 2.0 / GLB, COLLADA (DAE) und 3MF. Die FBX-Datei Tokenisierung wird teilweise unterstützt, aber das vollständige Parsen ist noch nicht abgeschlossen.

Wird bei der Aufladung einer OBJ-Datei auch die .mtl Was ist das Material?

Ja, wenn… ObjLoadOptions.enable_materials = True Die Bibliothek sucht nach den .mtl Datei in demselben Verzeichnis wie die .obj Die Kommission hat die .mtl Die Geometrie ist noch geladen und eine Warnung wird ausgesendet.

Kann ich eine Datei aus einem Byte-Stream anstelle eines Pfades laden?

  • Ja, das ist gut. scene.open() Akzeptiert jedes Datei-ähnliche Objekt mit einem .read() Pass ein offenen binären Strom (z. B., io.BytesIO) direkt. Scene.from_file() Akzeptiert nur einen Dateipfad-Zeichen.

Wie bekomme ich Oberflächennormale?

Nach dem Laden überprüfen Sie: mesh.get_element(VertexElementType.NORMAL).Das gibt eine VertexElementNormal deren data Liste enthält einen normalen Vektor pro Referenz, der nach den folgenden Kennzeichnungen abgebildet ist: mapping_mode und . reference_mode.

from aspose.threed.entities import Mesh, VertexElementType

normals = mesh.get_element(VertexElementType.NORMAL)
if normals:
    print(normals.data[0])  # First normal vector

Ist das Library-Thread sicher für gleichzeitiges Laden mehrerer Dateien?

Jeder von ihnen Scene Objekt ist unabhängig. Lade einzelne Dateien in separate Scene Instanzen von separaten Threads ist sicher, solange Sie nicht teilen eine einzelne Scene über die Fäden ohne äußere Verriegelung.

 Deutsch