Wie man 3D-Modelle in Python konvertiert

Wie man 3D-Modelle in Python konvertiert

Die Formatkonvertierung mit Aspose.3D FOSS for Python ist ein zweistufiger Vorgang: Laden in ein Scene‑Objekt, dann Speichern in das gewünschte Ausgabeformat. Da alle Geometrien in einer gemeinsamen In‑Memory‑Repräsentation gehalten werden, sind keine format­spezifischen Zwischenschritte erforderlich. Die nachfolgenden Abschnitte zeigen die gängigsten Konvertierungen mit funktionierendem Code.

Schritt-für-Schritt-Anleitung

Schritt 1: Paket installieren

pip install aspose-3d-foss

Keine Systembibliotheken, Compiler oder zusätzlichen Laufzeitabhängigkeiten sind erforderlich.


Schritt 2: Laden des Quellmodells

Verwenden Sie Scene.from_file() für den einfachsten Fall: Das Format wird automatisch anhand der Dateierweiterung erkannt:

from aspose.threed import Scene

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

Für OBJ-Dateien, bei denen Sie die Kontrolle über das Koordinatensystem oder das Laden von Materialien benötigen, verwenden Sie scene.open() mit ObjLoadOptions:

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

options = ObjLoadOptions()
options.flip_coordinate_system = True  # Convert to Z-up if needed
options.enable_materials = True        # Load the accompanying .mtl file
options.normalize_normal = True

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

Beide Ansätze erzeugen ein identisches Scene‑Objekt für den nachfolgenden Speicher‑Schritt.


Schritt 3: Geladene Szene prüfen

Bevor Sie mit einer Konvertierung fortfahren, lohnt es sich zu überprüfen, ob die Geometrie korrekt geladen wurde. Eine fehlende Datei, ein nicht unterstütztes FBX-Feature oder ein Pfadproblem mit einer .mtl‑Datei können alle eine leere Szene erzeugen.

from aspose.threed import Scene
from aspose.threed.entities import Mesh

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

mesh_count = 0
total_vertices = 0

def count_meshes(node) -> None:
    global mesh_count, total_vertices
    for entity in node.entities:
        if isinstance(entity, Mesh):
            mesh_count += 1
            total_vertices += len(entity.control_points)
    for child in node.child_nodes:
        count_meshes(child)

count_meshes(scene.root_node)
print(f"Loaded {mesh_count} mesh(es), {total_vertices} total vertices")

if mesh_count == 0:
    raise ValueError("Scene contains no geometry: check the source file path and format")

Schritt 4: In das Zielformat speichern

Rufen Sie scene.save() mit dem Ausgabepfad auf. Übergeben Sie ein format‑spezifisches Save‑Options‑Objekt zur Steuerung von Binär‑ vs. ASCII‑Ausgabe, Koordinatenachsen und Kompression.

OBJ zu STL (binär)

from aspose.threed import Scene
from aspose.threed.formats import StlSaveOptions

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

save_opts = StlSaveOptions()
##StlSaveOptions defaults to binary output, which is more compact.

scene.save("model.stl", save_opts)
print("Saved model.stl")

OBJ zu glTF 2.0

from aspose.threed import Scene
from aspose.threed.formats import GltfSaveOptions

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

save_opts = GltfSaveOptions()

scene.save("model.gltf", save_opts)
print("Saved model.gltf")

Um als eigenständige GLB‑Binärdatei anstelle von .gltf + externen Puffern zu speichern, ändern Sie die Ausgabenerweiterung zu .glb:

scene.save("model.glb", save_opts)

OBJ zu 3MF

from aspose.threed import Scene
from aspose.threed.formats import ThreeMfSaveOptions

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

save_opts = ThreeMfSaveOptions()

scene.save("model.3mf", save_opts)
print("Saved model.3mf")

STL zu glTF 2.0

Das gleiche Muster gilt unabhängig vom Quellformat:

from aspose.threed import Scene
from aspose.threed.formats import GltfSaveOptions

scene = Scene.from_file("input.stl")
scene.save("output.gltf", GltfSaveOptions())
print("Saved output.gltf")

Schritt 5: Ausgabe überprüfen

Nach dem Speichern bestätigen Sie, dass die Ausgabedatei existiert und eine Größe ungleich Null hat. Für eine gründlichere Prüfung laden Sie sie erneut und vergleichen die Mesh‑Anzahlen:

import os
from aspose.threed import Scene
from aspose.threed.entities import Mesh

output_path = "model.stl"

##Basic file-system check
size = os.path.getsize(output_path)
print(f"Output file size: {size} bytes")
if size == 0:
    raise RuntimeError("Output file is empty: save may have failed silently")

##Round-trip verification: reload and count geometry
def _iter_nodes(node):
    yield node
    for child in node.child_nodes:
        yield from _iter_nodes(child)

reloaded = Scene.from_file(output_path)
mesh_count = sum(
    1
    for node in _iter_nodes(reloaded.root_node)
    for entity in node.entities
    if isinstance(entity, Mesh)
)
print(f"Round-trip check: {mesh_count} mesh(es) in output")

Häufige Probleme und Lösungen

Ausgabedatei wird erstellt, enthält jedoch keine Geometrie

Die Quelldatei wurde möglicherweise mit null Meshes geladen. Fügen Sie den Inspektionsschritt aus Schritt 3 vor dem Speichern hinzu. Stellen Sie außerdem sicher, dass die Dateierweiterung dem tatsächlichen Format entspricht; Aspose.3D verwendet die Erweiterung, um den Parser auszuwählen.

glTF-Ausgabe fehlt Texturen

Aspose.3D FOSS überträgt Geometrie‑ und Materialeigenschaften bei der Konvertierung. Wenn die Quell‑OBJ externe Bilddateien im .mtl referenziert, werden diese Bilddateien nicht automatisch zusammen mit dem .gltf kopiert. Kopieren Sie die Texturbilder nach dem Speichern manuell in das Ausgabeverzeichnis.

STL-Ausgabe sieht innen nach außen aus (Flächennormalen umgekehrt)

STL enthält keine Metadaten zur Windungsreihenfolge. Wenn die Ausgabennormalen invertiert sind, setzen Sie StlSaveOptions Optionen, falls verfügbar, oder drehen Sie das Koordinatensystem beim Laden um: ObjLoadOptions.flip_coordinate_system = True.

ValueError: unsupported format beim Speichern

Überprüfen Sie, ob die Ausgabedateierweiterung eine der .obj, .stl, .gltf, .glb, .dae, .3mf ist. Erweiterungen sind unter Linux case-sensitive.

Sehr große Dateien verursachen langsame Konvertierung

Aspose.3D FOSS verarbeitet Geometrie im Speicher. Für Dateien mit Millionen von Polygonen stellen Sie ausreichend RAM sicher. Derzeit gibt es keine Streaming‑Write‑API.


Häufig gestellte Fragen (FAQ)

Kann ich eine Datei konvertieren, ohne sie zuerst auf die Festplatte zu schreiben?

Ja. Sowohl scene.open() als auch scene.save() akzeptieren binäre, dateiähnliche Objekte zusätzlich zu Dateipfaden. Übergeben Sie jedes Objekt, das read() zum Laden oder write() zum Speichern implementiert:

import io
from aspose.threed import Scene

# Load from an in-memory buffer
data = open('model.obj', 'rb').read()
scene = Scene()
scene.open(io.BytesIO(data))

# Save to an in-memory buffer
buf = io.BytesIO()
scene.save(buf)

Wird FBX als Quellformat für die Konvertierung unterstützt?

Die Tokenisierung von FBX ist teilweise implementiert, aber der Parser ist nicht vollständig. FBX‑Eingaben können unvollständige Szenen erzeugen. Verwenden Sie OBJ, STL, glTF, COLLADA oder 3MF als zuverlässige Quellformate.

Werden Materialien eine OBJ-zu-glTF-Konvertierung überstehen?

Grundlegende Phong/Lambert‑Materialeigenschaften (Diffuse Farbe) werden durch das Scene‑Modell weitergegeben und in den glTF‑Materialblock geschrieben. Prozedurale oder benutzerdefinierte Shader‑Parameter, die im glTF‑Materialmodell nicht ausdrückbar sind, werden verworfen.

Kann ich mehrere Dateien in einer Schleife konvertieren?

Ja. Jeder Scene.from_file()-Aufruf erzeugt ein unabhängiges Objekt, sodass eine Schleife über eine Liste von Pfaden unkompliziert ist:

from pathlib import Path
from aspose.threed import Scene
from aspose.threed.formats import StlSaveOptions

source_dir = Path("input")
output_dir = Path("output")
output_dir.mkdir(exist_ok=True)

opts = StlSaveOptions()
for obj_file in source_dir.glob("*.obj"):
    scene = Scene.from_file(str(obj_file))
    out_path = output_dir / obj_file.with_suffix(".stl").name
    scene.save(str(out_path), opts)
    print(f"Converted {obj_file.name} -> {out_path.name}")

Behält die Konvertierung die Szenenhierarchie (Eltern/Kind‑Knoten) bei?

Ja. Der Knotenbaum wird so weit wie das Zielformat es zulässt erhalten. Formate wie STL speichern nur flache Geometrie ohne Knotenstruktur; die Hierarchie wird beim Speichern abgeflacht. Formate wie glTF und COLLADA behalten die vollständige Hierarchie bei.

 Deutsch