Funkcje i możliwości

Aspose.3D FOSS dla Python zapewnia kompletny interfejs API grafu sceny do odczytu, tworzenia i zapisu treści 3D w wielu standardowych formatach branżowych. Ta strona dokumentuje każdy główny obszar funkcji wraz z działającymi przykładami kodu Python, które używają rzeczywistego API biblioteki.

Instalacja i konfiguracja

Zainstaluj bibliotekę z PyPI za pomocą jednego polecenia:

pip install aspose-3d-foss

Nie są wymagane dodatkowe pakiety systemowe, natywne rozszerzenia ani łańcuchy narzędzi kompilatora. Biblioteka jest czystym Python i obsługuje Python 3.7‑3.12 na Windows, macOS i Linux.

Aby zweryfikować instalację:

from aspose.threed import Scene

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

Funkcje i możliwości

Obsługa formatów

Aspose.3D FOSS dla Python odczytuje i zapisuje następujące formaty:

FormatRozszerzenieOdczytZapisUwagi
Wavefront OBJ.objTakTak.obsługa ładowania materiałów .mtl
STL (binarny).stlTakTakWeryfikacja roundtrip (39 testów)
STL (ASCII).stlTakTakWeryfikacja roundtrip
glTF 2.0.gltfTakTakPełny graf sceny zachowany
GLB (binary glTF).glbTakTakJednoplikowy kontener binarny
COLLADA.daeTakTakHierarchia sceny i materiały
3MF.3mfTakTakFormat produkcji przyrostowej
FBX.fbxCzęściowyNieTokenizer działa; parser ma znane błędy

Ładowanie OBJ z opcjami

ObjLoadOptions kontroluje sposób parsowania plików OBJ:

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")

Zapisywanie do STL

StlSaveOptions kontroluje wyjście binarne vs. ASCII oraz inne ustawienia specyficzne dla STL:

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

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

Graf sceny

Cała zawartość 3D jest organizowana jako drzewo Node obiektów. Korzeń drzewa to scene.root_node. Każdy węzeł może zawierać węzły potomne i posiadać Entity (siatkę, kamerę lub światło) plus Transform.

Przeglądanie hierarchii sceny

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)

Tworzenie sceny programowo

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")

Inspekcja GlobalTransform

GlobalTransform określa transformację w przestrzeni świata węzła po zsumowaniu wszystkich transformacji przodków:

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}")

API siatki

Ten Mesh encja zapewnia dostęp do danych geometrycznych, w tym punktów kontrolnych (wierzchołków), wielokątów oraz elementów wierzchołków dla normalnych, UV i kolorów.

Odczytywanie geometrii siatki

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)}")

Dostęp do elementów wierzchołkowych

Elementy wierzchołkowe zawierają dane per-wierzchołkowe lub per-wielokątne. Najbardziej powszechne elementy to normalne, współrzędne UV, kolory wierzchołków oraz grupy wygładzania:

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)}")

System materiałów

Aspose.3D FOSS obsługuje dwa typy materiałów: LambertMaterial (cieniowanie dyfuzyjne) i PhongMaterial (specular shading). Oba są ładowane automatycznie z plików .mtl podczas używania ObjLoadOptions z enable_materials = True.

Odczytywanie materiałów z OBJ

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}")

Przypisywanie materiału programowo

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")

Narzędzia matematyczne

Ten aspose.threed.utilities moduł zapewnia wszystkie typy matematyki geometrycznej potrzebne do konstrukcji i inspekcji sceny.

KlasaCel
Vector22D floating-point vector (UV coordinates)
Vector33D double-precision vector (positions, normals)
Vector44D double-precision vector (homogeneous coordinates)
FVector33D single-precision vector (compact storage)
QuaternionReprezentacja rotacji bez zjawiska gimbal lock
Matrix44×4 transformation matrix
BoundingBoxProstopadłościan ograniczający wyrównany do osi z narożnikami min/max

Praca z transformacjami

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}")

Obliczanie pudełka ograniczającego

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})")

Animacja

Aspose.3D FOSS udostępnia model animacji oparty na AnimationClip, AnimationNode, KeyFrame, oraz KeyframeSequence. Dane animacji przechowywane w załadowanych plikach (glTF, COLLADA) są dostępne poprzez te obiekty.

Odczytywanie klipów animacji

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}")

Opcje ładowania i zapisu

Każdy obsługiwany format ma odpowiadającą mu klasę opcji, która kontroluje zachowanie parsowania i serializacji.

KlasaFormatKluczowe właściwości
ObjLoadOptionsOBJenable_materials, flip_coordinate_system, normalize_normal, scale
StlSaveOptionsSTLTryb wyjścia binarny vs. ASCII
(glTF używa wartości domyślnych)glTF / GLBGraf sceny i materiały zachowywane automatycznie

Przykłady użycia

Przykład 1: Konwersja formatu OBJ do STL

Konwertuj plik OBJ (z materiałami) do binarnego STL, wypisując statystyki siatki w trakcie:

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")

Przykład 2: Pakowanie wsadowe glTF do GLB

Zapisz ponownie katalog oddzielnych plików glTF + tekstur jako samodzielne pliki binarne GLB:

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)}")

Przykład 3: Inspekcja grafu sceny i raport eksportu

Przejdź graf sceny pliku COLLADA, zbierz statystyki dla każdej siatki i wydrukuj ustrukturyzowany raport:

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}"
    )

Wskazówki i najlepsze praktyki

Wybór formatu

  • glTF 2.0 / GLB jest zalecanym formatem wymiany dla scen, które zawierają materiały, animacje i złożone hierarchie. Preferuj GLB (binarny) zamiast glTF (tekst + pliki zewnętrzne) ze względu na przenośność.
  • STL jest właściwym wyborem, gdy odbiorcą końcowym jest slicer, narzędzie CAD lub jakiekolwiek narzędzie potrzebujące jedynie geometrii. STL nie zawiera danych o materiałach ani animacjach.
  • OBJ jest szeroko wspierany i dobrym wyborem, gdy dane materiałowe muszą być wymieniane ze starszymi narzędziami. Zawsze przechowuj plik .mtl razem z plikiem .obj.

Systemy współrzędnych

  • Różne aplikacje używają różnych konwencji praworęczności. Ustaw ObjLoadOptions.flip_coordinate_system = True przy importowaniu plików OBJ z narzędzi, które używają układu współrzędnych praworęcznego, jeśli Twój potok oczekuje współrzędnych leworęcznych, i odwrotnie.
  • Sprawdź konwencję osi źródłowego zasobu przed zastosowaniem jakiegokolwiek odbicia. Podwójne odbicie powoduje nieprawidłową geometrię.

Normalizacja

  • Zawsze ustaw ObjLoadOptions.normalize_normal = True gdy downstreamowy potok oczekuje jednostkowych wektorów normalnych (na przykład przy przekazywaniu normalnych do shadera lub wykonywaniu obliczeń oświetlenia przy użyciu iloczynu skalarnego). Nieznormalizowane wektory normalne z źle sformatowanych plików OBJ powodują artefakty oświetleniowe.

Wydajność

  • Wczytuj pliki raz i przekształcaj scenę w pamięci zamiast ponownego ładowania z dysku dla każdego formatu wyjściowego. Jedno Scene.from_file() wywołanie, po którym następuje wiele scene.save() wywołań jest bardziej wydajne niż wielokrotne ładowania.
  • Podczas przetwarzania dużych partii, utwórz pojedynczy ObjLoadOptions lub StlSaveOptions instancję i używaj jej we wszystkich plikach zamiast tworzyć nowy obiekt opcji dla każdego pliku.

Obsługa błędów

  • Zawijaj scene.open() i scene.save() wywołania w try/except bloki podczas przetwarzania nieufnych lub dostarczonych przez użytkownika plików. Zgłaszaj nazwę pliku w komunikatach wyjątków, aby uprościć debugowanie w potokach wsadowych.

Typowe problemy

ProblemPrzyczynaRozwiązanie
Siatka wydaje się odbita lustrzanie po załadowaniuNiezgodność orientacji systemu współrzędnychPrzełącz ObjLoadOptions.flip_coordinate_system
Normalne mają zerową długośćPlik źródłowy ma nieznormalizowane wektory normalneUstaw ObjLoadOptions.normalize_normal = True
Materiały nie zostały załadowane z OBJenable_materials jest False (domyślnie)Ustaw ObjLoadOptions.enable_materials = True
Scena ładuje się, ale wszystkie węzły są pustePlik używa formatu FBXParser FBX jest w trakcie tworzenia; użyj zamiast tego OBJ, STL lub glTF
Model jest niezwykle mały lub dużyPlik źródłowy używa jednostek nie‑metrycznychZastosuj ObjLoadOptions.scale aby przeliczyć na jednostkę docelową
AttributeError na mesh.polygonsEncja węzła nie jest siatkąZabezpiecz przy użyciu if node.entity is not None przed dostępem do właściwości encji
Plik GLB został odrzucony przez przeglądarkęZapisano z .gltf rozszerzenieUżyj .glb rozszerzenie przy wywoływaniu scene.save() aby uruchomić kontener binarny

Najczęściej zadawane pytania

Jakie wersje Python są obsługiwane? Python 3.7, 3.8, 3.9, 3.10, 3.11 i 3.12 są wszystkie obsługiwane. Biblioteka jest czystym Python bez natywnych rozszerzeń, więc działa na każdej platformie, na której działa CPython.

Czy biblioteka ma jakiekolwiek zewnętrzne zależności? Nie. Aspose.3D FOSS dla Python używa wyłącznie standardowej biblioteki Python. Instalacja odbywa się jako pojedynczy pip install aspose-3d-foss polecenie bez dodatkowych kroków.

Czy FBX jest obsługiwany? Tokenizer FBX jest zaimplementowany i potrafi parsować binarny strumień tokenów FBX, ale konstruktor grafu sceny oparty na tokenizerze ma znane błędy i nie jest gotowy do produkcji. Użyj OBJ, STL, glTF, COLLADA lub 3MF do niezawodnego zastosowania produkcyjnego.

Czy mogę używać Aspose.3D FOSS w produkcie komercyjnym? Tak. Biblioteka jest wydana na licencji MIT, która zezwala na użycie w oprogramowaniu własnościowym i komercyjnym bez opłat licencyjnych, pod warunkiem dołączenia informacji o licencji.

Jak zgłosić błąd lub poprosić o format? Otwórz zgłoszenie w repozytorium. Dołącz minimalny plik reprodukujący oraz wersję Python, system operacyjny i wersję biblioteki z pip show aspose-3d-foss.


Podsumowanie referencji API

Klasy podstawowe

  • Scene: Kontener najwyższego poziomu dla sceny 3D. Punkt wejścia dla open(), from_file(), i save().
  • Node: Węzeł drzewa w grafie sceny. Zawiera entity, transform, global_transform, material, child_nodes, i name.
  • Entity: Klasa bazowa dla obiektów dołączonych do węzłów (Mesh, Camera, Light).
  • Transform: Pozycja, rotacja (Quaternion) i skala w przestrzeni lokalnej dla węzła.
  • GlobalTransform: Transformacja w przestrzeni światowej tylko do odczytu, obliczana przez kumulowanie wszystkich transformacji przodków.

Geometry

  • Mesh: Siatka wielokątowa z control_points (lista wierzchołków) i polygons.
  • VertexElementNormal: Wektory normalne per-wierzchołkowe lub per-wielokątne.
  • VertexElementUV: Współrzędne tekstury UV per-wierzchołkowe.
  • VertexElementVertexColor: Dane koloru per‑wierzchołkowe.
  • VertexElementSmoothingGroup: Przypisania grup wygładzania wielokątów.

Materiały

  • LambertMaterial: Model cieniowania rozproszonego z diffuse_color : i emissive_color.
  • PhongMaterial: Model cieniowania odbicia dodający specular_color : i shininess.

: Narzędzia matematyczne (aspose.threed.utilities)

  • Vector2: Wektor 2D.
  • Vector3: Wektor 3D podwójnej precyzji.
  • Vector4: Wektor 4D podwójnej precyzji.
  • FVector3: Wektor 3D pojedynczej precyzji.
  • Quaternion: Quaternion obrotu z from_angle_axis() : i to_matrix().
  • Matrix4: macierz przekształcenia 4×4.
  • BoundingBox: Prostopadłościan ograniczający wyrównany do osi z minimum : i maximum : wierzchołkami.

Animacja

  • AnimationClip: Nazwany kontener dla zestawu kanałów animacji i ich klatek kluczowych.
  • AnimationNode: Dane animacji per-węzeł w klipie.
  • KeyFrame: Pojedyncza klatka kluczowa z czasem i wartością.
  • KeyframeSequence: Uporządkowana sekwencja klatek kluczowych dla jednej animowanej właściwości.

Opcje ładowania / zapisu

  • ObjLoadOptions: Ustawienia ładowania specyficzne dla OBJ: enable_materials, flip_coordinate_system, normalize_normal, scale.
  • StlSaveOptions: Ustawienia zapisu specyficzne dla STL (tryb binarny vs. tryb ASCII).

Kamery i światła

  • Camera: Obiekt kamery z ustawieniami projekcji, możliwy do dołączenia do a Node.
  • Light: Obiekt źródła światła, możliwy do dołączenia do a Node.
 Polski