Funktionen und Merkmale

Aspose.3D FOSS für Python bietet eine vollständige Scene-Graph-API zum Lesen, Erstellen und Schreiben von 3D-Inhalten in mehreren branchenüblichen Formaten. Diese Seite dokumentiert jeden wichtigen Funktionsbereich mit funktionierenden Python-Codebeispielen, die die tatsächliche Bibliotheks-API verwenden.

Installation und Einrichtung

Installieren Sie die Bibliothek von PyPI mit einem einzigen Befehl:

pip install aspose-3d-foss

Es sind keine zusätzlichen Systempakete, nativen Erweiterungen oder Compiler-Toolchains erforderlich. Die Bibliothek ist reines Python und unterstützt Python 3.7 bis 3.12 unter Windows, macOS und Linux.

Um die Installation zu überprüfen:

from aspose.threed import Scene

scene = Scene()
print("Aspose.3D FOSS installed successfully")
print(f"Root node name: {scene.root_node.name}")

Funktionen und Merkmale

Formatunterstützung

Aspose.3D FOSS für Python liest und schreibt die folgenden Formate:

FormatErweiterungLesenSchreibenHinweise
Wavefront OBJ.objJaJa.mtl-Materialladen unterstützt
STL (binär).stlJaJaRoundtrip verifiziert (39 Tests)
STL (ASCII).stlJaJaRoundtrip verifiziert
glTF 2.0.gltfJaJaVollständiger Szenengraph erhalten
GLB (binary glTF).glbJaJaEinzeldatei-Binärcontainer
COLLADA.daeJaJaSzenenhierarchie und Materialien
3MF.3mfJaJaAdditives Fertigungsformat
FBX.fbxTeilweiseNeinTokenizer funktioniert; Parser hat bekannte Fehler

Laden von OBJ mit Optionen

ObjLoadOptions steuert, wie OBJ-Dateien geparst werden:

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

options = ObjLoadOptions()
options.enable_materials = True        # Load accompanying .mtl file
options.flip_coordinate_system = False # Preserve original handedness
options.normalize_normal = True        # Normalize vertex normals to unit length
options.scale = 1.0                    # Apply a uniform scale factor at load time

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

print(f"Loaded {len(scene.root_node.child_nodes)} top-level nodes")

Speichern nach STL

StlSaveOptions steuert die binäre vs. ASCII-Ausgabe und andere STL-spezifische Einstellungen:

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

scene = Scene.from_file("model.obj")
options = StlSaveOptions()
scene.save("output.stl", options)

Scene-Graph

Alle 3D-Inhalte sind als Baum von Node Objekten. Die Wurzel des Baumes ist scene.root_node. Jeder Knoten kann Kindknoten enthalten und ein Entity (mesh, camera, or light) plus ein Transform.

Durchlaufen der Szenenhierarchie

from aspose.threed import Scene

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

def traverse(node, depth=0):
    indent = "  " * depth
    entity_type = type(node.entity).__name__ if node.entity else "none"
    print(f"{indent}{node.name} [{entity_type}]")
    for child in node.child_nodes:
        traverse(child, depth + 1)

traverse(scene.root_node)

Programmatisches Erstellen einer Szene

from aspose.threed import Scene, Node, Entity
from aspose.threed.entities import Mesh
from aspose.threed.utilities import Vector3

scene = Scene()
root = scene.root_node

##Create a child node and position it
child = root.create_child_node("my_object")
child.transform.translation = Vector3(1.0, 0.0, 0.0)
child.transform.scaling = Vector3(2.0, 2.0, 2.0)

scene.save("constructed.glb")

Untersuchen von GlobalTransform

GlobalTransform gibt die Welt-Raum-Transformation eines Knotens nach dem Aufsummieren aller Vorfahren-Transformationen an:

from aspose.threed import Scene

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

for node in scene.root_node.child_nodes:
    gt = node.global_transform
    print(f"Node: {node.name}")
    print(f"  World translation: {gt.translation}")
    print(f"  World scale: {gt.scale}")

Mesh-API

Der Mesh Entität bietet Zugriff auf Geometriedaten einschließlich Kontrollpunkten (vertices), Polygonen und Vertex-Elementen für normals, UVs und Farben.

Mesh-Geometrie lesen

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

options = ObjLoadOptions()
options.enable_materials = True
options.flip_coordinate_system = False

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

for node in scene.root_node.child_nodes:
    if node.entity is None:
        continue
    mesh = node.entity
    print(f"Mesh: {node.name}")
    print(f"  Vertices: {len(mesh.control_points)}")
    print(f"  Polygons: {len(mesh.polygons)}")

Zugriff auf Vertex-Elemente

Vertex-Elemente enthalten pro-Vertex- oder pro-Polygon-Daten. Die gebräuchlichsten Elemente sind Normalen, UV-Koordinaten, Vertex-Farben und Glättungsgruppen:

from aspose.threed import Scene
from aspose.threed.entities import VertexElementNormal, VertexElementUV

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

for node in scene.root_node.child_nodes:
    if node.entity is None:
        continue
    mesh = node.entity

    # Iterate vertex elements to find normals and UVs
    for element in mesh.vertex_elements:
        if isinstance(element, VertexElementNormal):
            print(f"  Normals count: {len(element.data)}")
        elif isinstance(element, VertexElementUV):
            print(f"  UV count: {len(element.data)}")

Materialsystem

Aspose.3D FOSS unterstützt zwei Materialtypen: LambertMaterial (diffuse shading) und PhongMaterial (specular shading). Beide werden automatisch aus .mtl-Dateien geladen, wenn verwendet ObjLoadOptions mit enable_materials = True.

Materialien aus OBJ lesen

from aspose.threed import Scene
from aspose.threed.shading import LambertMaterial, PhongMaterial
from aspose.threed.formats import ObjLoadOptions

options = ObjLoadOptions()
options.enable_materials = True

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

for node in scene.root_node.child_nodes:
    mat = node.material
    if mat is None:
        continue
    print(f"Node: {node.name}")
    if isinstance(mat, PhongMaterial):
        print(f"  Type: Phong")
        print(f"  Diffuse: {mat.diffuse_color}")
        print(f"  Specular: {mat.specular_color}")
    elif isinstance(mat, LambertMaterial):
        print(f"  Type: Lambert")
        print(f"  Diffuse: {mat.diffuse_color}")

Material programmgesteuert zuweisen

from aspose.threed import Scene, Node
from aspose.threed.shading import PhongMaterial
from aspose.threed.utilities import Vector3

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

material = PhongMaterial()
material.diffuse_color = Vector3(0.8, 0.2, 0.2)   # Red diffuse
material.specular_color = Vector3(1.0, 1.0, 1.0)  # White specular

##Apply to the first mesh node
for node in scene.root_node.child_nodes:
    if node.entity is not None:
        node.material = material
        break

scene.save("recolored.glb")

Mathematische Hilfsfunktionen

Der aspose.threed.utilities Das Modul stellt alle geometrischen Mathematiktypen bereit, die für den Szenenaufbau und die Inspektion benötigt werden.

KlasseZweck
Vector22D floating-point vector (UV coordinates)
Vector33D double-precision vector (positions, normals)
Vector44D double-precision vector (homogeneous coordinates)
FVector33D single-precision vector (compact storage)
QuaternionRotationsdarstellung ohne Gimbal-Lock
Matrix44×4 transformation matrix
BoundingBoxAchsenorientierte Bounding-Box mit Minimal-/Maximal-Ecken

Arbeiten mit Transformationen

from aspose.threed.utilities import Vector3, Quaternion, Matrix4
import math

##Build a rotation quaternion from axis-angle
axis = Vector3(0.0, 1.0, 0.0)          # Y-axis
angle_rad = math.radians(45.0)
q = Quaternion.from_angle_axis(angle_rad, axis)

print(f"Quaternion: x={q.x:.4f} y={q.y:.4f} z={q.z:.4f} w={q.w:.4f}")

##Convert to rotation matrix
mat = q.to_matrix()
print(f"Rotation matrix row 0: {mat[0, 0]:.4f} {mat[0, 1]:.4f} {mat[0, 2]:.4f}")

Berechnung einer Bounding Box

from aspose.threed import Scene

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

# NOTE: mesh.get_bounding_box() is a stub — it always returns an empty BoundingBox()
# regardless of geometry. Compute bounds manually from control_points:
for node in scene.root_node.child_nodes:
    if node.entity is None:
        continue
    mesh = node.entity
    pts = mesh.control_points  # returns a copy of the vertex list
    if not pts:
        continue
    xs = [p.x for p in pts]
    ys = [p.y for p in pts]
    zs = [p.z for p in pts]
    print(f"Mesh: {node.name}")
    print(f"  Min: ({min(xs):.3f}, {min(ys):.3f}, {min(zs):.3f})")
    print(f"  Max: ({max(xs):.3f}, {max(ys):.3f}, {max(zs):.3f})")

Animation

Aspose.3D FOSS bietet ein Animationsmodell basierend auf AnimationClip, AnimationNode, KeyFrame, und KeyframeSequence. Animationsdaten, die in geladenen Dateien (glTF, COLLADA) gespeichert sind, sind über diese Objekte zugänglich.

Einlesen von Animationsclips

from aspose.threed import Scene

scene = Scene.from_file("animated.glb")

for clip in scene.animation_clips:
    print(f"Clip: {clip.name}  ({clip.start:.2f}s – {clip.stop:.2f}s)")
    for anim_node in clip.animations:
        print(f"  Animation node: {anim_node.name}")
        for sub in anim_node.sub_animations:
            print(f"    Sub-animation: {sub.name}")
        for bp in anim_node.bind_points:
            print(f"    Bind point: {bp.name}")

Lade- und Speicheroptionen

Jedes unterstützte Format hat eine entsprechende Optionsklasse, die das Parsing- und Serialisierungsverhalten steuert.

KlasseFormatWichtige Eigenschaften
ObjLoadOptionsOBJenable_materials, flip_coordinate_system, normalize_normal, scale
StlSaveOptionsSTLBinär- vs. ASCII-Ausgabemodus
(glTF verwendet Vorgaben)glTF / GLBSzenengraph und Materialien werden automatisch erhalten

Beispiele zur Verwendung

Beispiel 1: OBJ-zu-STL-Formatkonvertierung

Konvertiere eine OBJ-Datei (mit Materialien) in binäres STL und gib dabei Mesh-Statistiken aus:

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

##Load OBJ with material support
load_opts = ObjLoadOptions()
load_opts.enable_materials = True
load_opts.flip_coordinate_system = False
load_opts.normalize_normal = True

scene = Scene()
scene.open("input.obj", load_opts)

##Report what was loaded
total_vertices = 0
total_polygons = 0
for node in scene.root_node.child_nodes:
    if node.entity is not None:
        mesh = node.entity
        total_vertices += len(mesh.control_points)
        total_polygons += len(mesh.polygons)
        print(f"  {node.name}: {len(mesh.control_points)} vertices, {len(mesh.polygons)} polygons")

print(f"Total: {total_vertices} vertices, {total_polygons} polygons")

##Save as STL
save_opts = StlSaveOptions()
scene.save("output.stl", save_opts)
print("Saved output.stl")

Beispiel 2: Stapelverarbeitung von glTF zu GLB

Speichere ein Verzeichnis mit separaten glTF‑ und Texturdateien erneut als eigenständige GLB‑Binärdateien:

import os
from aspose.threed import Scene

input_dir = "gltf_files"
output_dir = "glb_files"
os.makedirs(output_dir, exist_ok=True)

for filename in os.listdir(input_dir):
    if not filename.endswith(".gltf"):
        continue
    src = os.path.join(input_dir, filename)
    dst = os.path.join(output_dir, filename.replace(".gltf", ".glb"))
    scene = Scene.from_file(src)
    scene.save(dst)
    print(f"Packed {filename} -> {os.path.basename(dst)}")

Beispiel 3: Inspektion des Szenengraphen und Exportbericht

Durchlaufe den Szenengraph einer COLLADA-Datei, sammle Mesh‑spezifische Statistiken und gib einen strukturierten Bericht aus:

from aspose.threed import Scene

scene = Scene.from_file("assembly.dae")

report = []

def collect(node, path=""):
    full_path = f"{path}/{node.name}" if node.name else path
    if node.entity is not None:
        mesh = node.entity
        gt = node.global_transform
        report.append({
            "path": full_path,
            "vertices": len(mesh.control_points),
            "polygons": len(mesh.polygons),
            "world_x": gt.translation.x,
            "world_y": gt.translation.y,
            "world_z": gt.translation.z,
        })
    for child in node.child_nodes:
        collect(child, full_path)

collect(scene.root_node)

print(f"{'Path':<40} {'Verts':>6} {'Polys':>6} {'X':>8} {'Y':>8} {'Z':>8}")
print("-" * 78)
for entry in report:
    print(
        f"{entry['path']:<40} "
        f"{entry['vertices']:>6} "
        f"{entry['polygons']:>6} "
        f"{entry['world_x']:>8.3f} "
        f"{entry['world_y']:>8.3f} "
        f"{entry['world_z']:>8.3f}"
    )

Tipps und bewährte Verfahren

Formatauswahl

  • glTF 2.0 / GLB ist das empfohlene Austauschformat für Szenen, die Materialien, Animationen und komplexe Hierarchien enthalten. Bevorzuge GLB (binär) gegenüber glTF (Text + externe Dateien) für Portabilität.
  • STL ist die richtige Wahl, wenn der nachgelagerte Verbraucher ein Slicer, ein CAD‑Tool oder ein beliebiges Werkzeug ist, das nur Geometrie benötigt. STL enthält keine Material‑ oder Animationsdaten.
  • OBJ ist weit verbreitet und eine gute Wahl, wenn Materialdaten mit älteren Werkzeugen ausgetauscht werden müssen. Bewahre die .mtl‑Datei stets zusammen mit der .obj‑Datei auf.

Koordinatensysteme

  • Verschiedene Anwendungen verwenden unterschiedliche Rechts- bzw. Linkshändigkeitskonventionen. Set ObjLoadOptions.flip_coordinate_system = True wenn Sie OBJ-Dateien von Werkzeugen importieren, die ein rechtshändiges Koordinatensystem verwenden, während Ihre Pipeline linkshändige Koordinaten erwartet, und umgekehrt.
  • Überprüfen Sie die Achsenkonvention des Quell‑Assets, bevor Sie irgendeine Spiegelung anwenden. Ein doppeltes Spiegeln erzeugt falsche Geometrie.

Normalisierung

  • Immer setzen ObjLoadOptions.normalize_normal = True wenn die nachgelagerte Pipeline Einheitsnormalen erwartet (zum Beispiel beim Weitergeben von Normalen an einen Shader oder bei Dot-Product-Beleuchtungsberechnungen). Nicht normalisierte Normalen aus fehlerhaft erzeugten OBJ-Dateien verursachen Beleuchtungsartefakte.

Leistung

  • Laden Sie Dateien einmal und transformieren Sie den In-Memory-Szenengraphen, anstatt für jedes Ausgabeformat von der Festplatte neu zu laden. Ein einzelnes Scene.from_file() Aufruf, gefolgt von mehreren scene.save() Aufrufe sind effizienter als wiederholtes Laden.
  • Beim Verarbeiten großer Stapel, erstellen Sie ein einzelnes ObjLoadOptions oder StlSaveOptions Instanz und verwenden Sie diese für alle Dateien wieder, anstatt für jede Datei ein neues Options-Objekt zu erstellen.

Fehlerbehandlung

  • Wrap scene.open() und scene.save() Aufrufe in try/except blockiert bei der Verarbeitung von nicht vertrauenswürdigen oder vom Benutzer bereitgestellten Dateien. Gibt den Dateinamen in Ausnahme­meldungen aus, um das Debuggen in Batch‑Pipelines zu vereinfachen.

Häufige Probleme

ProblemUrsacheLösung
Mesh erscheint nach dem Laden gespiegeltInkonsistenz der Handedness des KoordinatensystemsUmschalten ObjLoadOptions.flip_coordinate_system
Normalen haben null LängeQuelldatei enthält nicht normalisierte NormalenSetzen ObjLoadOptions.normalize_normal = True
Materialien nicht aus OBJ geladenenable_materials ist False (Standard)Setzen ObjLoadOptions.enable_materials = True
Szene wird geladen, aber alle Knoten sind leerDatei verwendet das FBX-FormatFBX-Parser ist in Arbeit; verwenden Sie stattdessen OBJ, STL oder glTF
Modell ist extrem klein oder großQuelldatei verwendet nicht-metrische EinheitenAnwenden ObjLoadOptions.scale um in Ihre Ziel‑Einheit zu konvertieren
AttributeError ein mesh.polygonsKnoten‑Entität ist kein MeshSchütze mit if node.entity is not None bevor Sie auf Entitätseigenschaften zugreifen
GLB-Datei wird vom Viewer abgelehntGespeichert mit .gltf ErweiterungVerwenden .glb Erweiterung beim Aufruf scene.save() um einen Binärcontainer auszulösen

Häufig gestellte Fragen

Welche Python-Versionen werden unterstützt? Python 3.7, 3.8, 3.9, 3.10, 3.11 und 3.12 werden alle unterstützt. Die Bibliothek ist reines Python ohne native Erweiterung, sodass sie auf jeder Plattform funktioniert, auf der CPython läuft.

Hat die Bibliothek externe Abhängigkeiten? Nein. Aspose.3D FOSS für Python verwendet ausschließlich die Python-Standardbibliothek. Es wird als ein einzelnes pip install aspose-3d-foss Kommando ohne weitere Schritte.

Wird FBX unterstützt? Der FBX-Tokenizer ist implementiert und kann den binären FBX-Token-Stream parsen, aber der darauf aufbauende Szenengraph-Builder weist bekannte Fehler auf und ist nicht produktionsreif. Verwenden Sie OBJ, STL, glTF, COLLADA oder 3MF für einen zuverlässigen Produktionseinsatz.

Kann ich Aspose.3D FOSS in einem kommerziellen Produkt verwenden? Ja. Die Bibliothek wird unter der MIT-Lizenz veröffentlicht, die die Nutzung in proprietärer und kommerzieller Software ohne Lizenzgebühren erlaubt, vorausgesetzt, der Lizenzhinweis wird beigefügt.

Wie melde ich einen Fehler oder fordere ein Format an? Öffnen Sie ein Issue im Repository. Fügen Sie eine minimale Reproduktionsdatei sowie die Python-Version, das Betriebssystem und die Bibliotheksversion bei. pip show aspose-3d-foss.


API-Referenzübersicht

Kernklassen

  • Scene: Container der obersten Ebene für eine 3D‑Szene. Einstiegspunkt für open(), from_file(), und save().
  • Node: Baumknoten im Szenengraphen. Trägt entity, transform, global_transform, material, child_nodes, und name.
  • Entity: Basisklasse für an Knoten angehängte Objekte (Mesh, Camera, Light).
  • Transform: Lokale Position, Rotation (Quaternion) und Skalierung für einen Knoten.
  • GlobalTransform: Nur lesbare Welt‑Raum-Transformation, die durch Akkumulieren aller übergeordneten Transformationen berechnet wird.

Geometrie

  • Mesh: Polygonnetz mit control_points (Vertexliste) und polygons.
  • VertexElementNormal: Pro‑Vertex‑ oder Pro‑Polygon‑Normalenvektoren.
  • VertexElementUV: Pro‑Vertex‑UV‑Texturkoordinaten.
  • VertexElementVertexColor: Pro-Vertex-Farbdaten.
  • VertexElementSmoothingGroup: Polygon-Glättungsgruppen-Zuweisungen.

Materialien

  • LambertMaterial: Diffuses Shading-Modell mit diffuse_color : und emissive_color.
  • PhongMaterial: Spekulares Shading-Modell, das hinzufügt specular_color : und shininess.

: Mathe‑Hilfsfunktionen (aspose.threed.utilities)

  • Vector2: 2D-Vektor.
  • Vector3: 3D-Doppelpräzisionsvektor.
  • Vector4: 4D-Doppelpräzisionsvektor.
  • FVector3: 3D-Einzelpräzisionsvektor.
  • Quaternion: Rotationsquaternion mit from_angle_axis() und to_matrix().
  • Matrix4: 4×4-Transformationsmatrix.
  • BoundingBox: Achsenorientierte Begrenzungsbox mit minimum und maximum Ecken.

Animation

  • AnimationClip: Benannter Container für einen Satz von Animationskanälen und deren Schlüsselbilder.
  • AnimationNode: Pro‑Knoten‑Animationsdaten innerhalb eines Clips.
  • KeyFrame: Einzelnes Schlüsselbild mit Zeit und Wert.
  • KeyframeSequence: Geordnete Sequenz von Schlüsselbildern für eine einzelne animierte Eigenschaft.

Lade‑/Speicheroptionen

  • ObjLoadOptions: OBJ-spezifische Ladevorgaben: enable_materials, flip_coordinate_system, normalize_normal, scale.
  • StlSaveOptions: STL-spezifische Speicherungseinstellungen (binär vs. ASCII-Modus).

Kameras und Lichter

  • Camera: Kamera-Entität mit Projektions-Einstellungen, anfügbar an ein Node.
  • Light: Lichtquellen-Entität, anfügbar an ein Node.
 Deutsch