Jak zainstalować modele 3D w Pythonie

Jak zainstalować modele 3D w Pythonie

Aspose.3D FOSS dla Pythona zapewnia prostą API do otwarcia plików 3D bez żadnych zależności. po załadowaniu pliku w Scene Obiekt, można przejść hierarchii węzłów i przeczytać surowe dane geometryczne dla każdego z nich na scenie.

Przewodnik krok po kroku

Krok 1: Instalacja pakietu

Instaluj Aspose.3D FOSS z PyPI. Nie wymagane są dodatkowe biblioteki systemowe.

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

Wspierane wersje Pythona: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.


Krok 2: Wprowadzenie klasy scenicznej

i The Scene Klasy są najwyższym pojemnikiem dla wszystkich danych 3D. Importować je wraz z dowolnymi klasami opcji obciążenia potrzebne.

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

Wszystkie klasy publiczne żyją pod aspose.threed lub jego podpakowania (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).


Krok 3: Pobierz plik

Użyj statycznego Scene.from_file() metoda otwierania dowolnego obsługiwanego formatu. biblioteka automatycznie wykrywa format z rozszerzenia pliku.

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

Alternatywnie, tworzyć A Scene Instancja i wezwanie open();Przydatne, gdy chcesz przejść opcje ładowania lub wyraźnie radzić sobie z błędami:

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

Oba metody obsługują pliki OBJ, STL (binary i ASCII), glTF 2.0 / GLB, COLLADA (DAE) i 3MF.


Krok 4: Przechodź przez scenę

„Przemocny sceną jest drzewo Node Obiekty z korzeniami w scene.root_node.Iterate recursively, aby znaleźć wszystkie węzły:

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)

Każdy z nich Node Można przewozić zero lub więcej. Entity obiekty (meczety, kamery, światła) sprawdź node.entities Zobacz co jest przywiązane.


Krok 5: Dostęp do danych Vertex i Polygon

Wprowadź podmiot węzła do Mesh i przeczytaj jego punkty kontrolne (pozycje odwrotne) i poligony (listy indeksów twarzy):

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 Jest to lista Vector4 przedmioty ; x, y, z Wziąć pozycję i w Jest to koordynacja homogenna (zazwyczaj 1.0).

mesh.polygons jest listą list z całości, w których każda lista wewnętrzna jest zamówionym zestawem indeksów punktów kontrolnych dla jednej twarzy.


Krok 6: Wprowadź opcje ładowania specyficzne dla formatu

Aby uzyskać kontrolę nad tym, jak jest interpretowany plik OBJ, przejdź do ObjLoadOptions Przykładem jest 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)

W przypadku plików STL, równowartość klasy jest StlLoadOptions.W przypadku GST, użyj GltfLoadOptions.Zobacz The Referencje API Dla pełnej listy.


Wspólne problemy i rozwiązania

FileNotFoundError podczas rozmowy Scene.from_file()

Droga musi być absolutna lub poprawna w stosunku do dyrektora roboczego w czasie pracy. pathlib.Path Aby stworzyć wiarygodne drogi:

from pathlib import Path
from aspose.threed import Scene

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

mesh.polygons jest puste po pobraniu pliku STL

Archiwum STL przechowują trójkąt jako surowe strony, a nie indeksowane łodygi. po ładowaniu poligony są syntetyzowane z tych stron. polygons Wygląda pusty, sprawdź len(mesh.control_points);Jeśli liczba jest wieloma z 3 geometry są przechowywane w nieindeksowanej formie, a każda kolejna trójkątność pionów tworzy jeden trojuł.

System koordynacyjny nie jest zgodny (model pojawia się z rotacją lub lustrem)

Różne narzędzia używają różnych konwencji (Y-up vs Z-Up, lewą ręką vs prawą). ObjLoadOptions.flip_coordinate_system = True lub zastosowanie rotacji do korzeniowego węzła Transform po ładowaniu.

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

Lista podmiotów w przyciskach może zawierać podmioty nieprzyłączone (kamera, światła). isinstance(entity, Mesh) Przed castingem.


Często zadawane pytania (FAQ)

Jakie formaty 3D można pobrać?

OBJ (Wavefront), STL (binary i ASCII), glTF 2.0 / GLB, COLLADA (DAE) i 3MF. Tokenizacja plików FBX jest częściowo obsługiwana, ale pełna parsing nie jest jeszcze kompletna.

Czy ładowanie pliku OBJ również ładuje .mtl Materiał ?

Tak, kiedy ObjLoadOptions.enable_materials = True Biblioteka poszukuje w tym celu .mtl w tym samym katalogu, jak i w .obj Artykuły - jeśli .mtl brakuje, geometria jest nadal obciążona i wyda się ostrzeżenie.

Czy mogę pobrać plik z prądu bytu zamiast ścieżki?

Tak i tak. scene.open() akceptuje dowolny obiekt podobny do pliku z A .read() metoda oprócz paska ścieżki pliku. przejść otwarty strumień binarny (np., io.BytesIOi bezpośrednio. Scene.from_file() Akceptuje tylko strzałkę ścieżki pliku.

Jak uzyskać normę powierzchniową?

Po wyładowaniu sprawdź mesh.get_element(VertexElementType.NORMAL).To powraca do A VertexElementNormal Które data Lista zawiera jeden wektor na odniesienie, mapowany według: mapping_mode i reference_mode.

from aspose.threed.entities import Mesh, VertexElementType

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

Czy biblioteka jest bezpieczna do ładowania wielu plików równocześnie?

Każdy z nich Scene Obiekt jest niezależny. Pobierz oddzielne pliki do odrębnych Scene Przykłady z oddzielnych filarów są bezpieczne, o ile nie udostępniasz jednego Scene Przez wiązki bez zamknięcia zewnętrznego.

 Polski