Jak zbudować siatkę 3D przy użyciu Aspose.3D w Python
Aspose.3D FOSS dla Python pozwala budować geometrię 3D całkowicie w kodzie: nie wymaga zewnętrznego narzędzia do modelowania. Tworzysz a Mesh, wypełniasz go pozycjami wierzchołków (control_points) oraz definicjami ścian (polygons), dołącz opcjonalne atrybuty wierzchołków, takie jak normalne, a następnie zapisz scenę w dowolnym obsługiwanym formacie.
Przewodnik krok po kroku
Krok 1: Zainstaluj pakiet
Zainstaluj Aspose.3D FOSS z PyPI. Nie są wymagane natywne rozszerzenia ani łańcuch narzędzi kompilatora.
pip install aspose-3d-fossSprawdź instalację:
from aspose.threed import Scene
print("Aspose.3D FOSS ready")Obsługiwane wersje Python: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.
Krok 2: Utwórz scenę i węzeł
Każda siatka musi znajdować się w grafie sceny. Utwórz a Scene i dodaj nazwany Node aby przechowywać siatkę:
from aspose.threed import Scene
scene = Scene()
node = scene.root_node.create_child_node("triangle")Nazwa węzła jest zachowywana w wyeksportowanym pliku i jest przydatna do debugowania oraz późniejszego odczytu za pomocą node.get_child("triangle").
Krok 3: Utwórz obiekt Mesh
Zainstancjuj a Mesh z opcjonalną opisową nazwą:
from aspose.threed.entities import Mesh
mesh = Mesh("triangle")Siatka jest początkowo pusta: brak wierzchołków, brak wielokątów. Wypełniasz ją w kolejnych krokach.
Krok 4: Dodaj punkty kontrolne (wierzchołki)
Punkty kontrolne to pozycje wierzchołków. Każdy wierzchołek jest przechowywany jako a Vector4(x, y, z, w) gdzie w=1 wskazuje punkt w przestrzeni 3D:
from aspose.threed.utilities import Vector4
##Vertex 0: origin
# Note: control_points returns a copy of the internal vertex list.
# Appending to the returned copy discards the vertex silently.
# Use _control_points to mutate the backing list directly.
# This is a known library limitation — a public add_control_point() API is not yet available.
mesh._control_points.append(Vector4(0.0, 0.0, 0.0, 1.0))
##Vertex 1: 1 unit along X
mesh._control_points.append(Vector4(1.0, 0.0, 0.0, 1.0))
##Vertex 2: apex
mesh._control_points.append(Vector4(0.5, 1.0, 0.0, 1.0))
print(f"Vertices added: {len(mesh.control_points)}")Ważne: mesh.control_points zwraca kopię wewnętrznej listy wierzchołków (getter wykonuje list(self._control_points)). Wywołanie mesh.control_points.append(v) dodaje do kopii, a nie do siatki, więc wierzchołek jest cicho odrzucany. Zawsze używaj mesh._control_points.append(v) do dodawania wierzchołków. Dostęp do prywatnego stanu poprzez _control_points jest znanym obejściem; interfejs może ulec zmianie w przyszłej wersji biblioteki.
Krok 5: Utwórz ściany wielokątów
Zdefiniuj topologię twarzy przy użyciu indeksów wierzchołków. Przekaż indeksy wierzchołków do create_polygon(). Trzy indeksy tworzą trójkąt; cztery tworzą czworokąt:
##Triangle: connect vertices 0 → 1 → 2
mesh.create_polygon(0, 1, 2)
print(f"Polygon count: {mesh.polygon_count}")Dla siatki czworokątnej należy przekazać cztery indeksy: mesh.create_polygon(0, 1, 2, 3).
Indeksy muszą być prawidłowymi pozycjami w control_points (indeksowane od zera, w zakresie). Kolejność wiązania jest przeciwnie do ruchu wskazówek zegara dla normalnych skierowanych na zewnątrz.
Krok 6: Dodaj normalne wierzchołków
Normalne wierzchołków są przechowywane jako a VertexElement dołączone do siatki. Użyj mesh.create_element() z VertexElementType.NORMAL, MappingMode.CONTROL_POINT, i ReferenceMode.DIRECT:
from aspose.threed.entities import VertexElementType, MappingMode, ReferenceMode, VertexElementNormal
from aspose.threed.utilities import Vector4, FVector4
##Create the normal element (returns VertexElementNormal, a VertexElementFVector subclass)
normals: VertexElementNormal = mesh.create_element(
VertexElementType.NORMAL,
MappingMode.CONTROL_POINT,
ReferenceMode.DIRECT
)
##One normal per vertex: all pointing out of the XY plane (0, 0, 1)
normals.set_data([
FVector4(0, 0, 1, 0), # vertex 0
FVector4(0, 0, 1, 0), # vertex 1
FVector4(0, 0, 1, 0), # vertex 2
])
print("Normal layer attached.")MappingMode.CONTROL_POINT oznacza jedną normalną na wierzchołek. ReferenceMode.DIRECT oznacza, że dane normalne są odczytywane w tej samej kolejności co punkty kontrolne (bez dodatkowego bufora indeksów).
Wektory normalne używają FVector4(x, y, z, w) z w=0 aby wskazać kierunek, a nie pozycję. FVector4 jest single-precision float vector; dane atrybutów wierzchołków w VertexElementFVector podklasy używają tego typu.
Krok 7: Dołącz siatkę do węzła i zapisz
Dodaj siatkę do węzła, a następnie zapisz scenę:
node.add_entity(mesh)
scene.save("triangle.gltf")
print("Saved triangle.gltf")Pełny działający skrypt (wszystkie kroki połączone):
from aspose.threed import Scene
from aspose.threed.entities import Mesh, VertexElementType, MappingMode, ReferenceMode, VertexElementNormal
from aspose.threed.utilities import Vector3, Vector4, FVector4
scene = Scene()
node = scene.root_node.create_child_node("triangle")
mesh = Mesh("triangle")
##Add 3 vertices (x, y, z, w)
# Use _control_points to mutate the backing list directly (control_points returns a copy)
mesh._control_points.append(Vector4(0.0, 0.0, 0.0, 1.0))
mesh._control_points.append(Vector4(1.0, 0.0, 0.0, 1.0))
mesh._control_points.append(Vector4(0.5, 1.0, 0.0, 1.0))
##Create a triangle polygon
mesh.create_polygon(0, 1, 2)
##Add normals (create_element returns VertexElementNormal, a VertexElementFVector subclass)
normals: VertexElementNormal = mesh.create_element(VertexElementType.NORMAL, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT)
normals.set_data([
FVector4(0, 0, 1, 0),
FVector4(0, 0, 1, 0),
FVector4(0, 0, 1, 0),
])
node.add_entity(mesh)
scene.save("triangle.gltf")Typowe problemy
| Problem | Rozwiązanie |
|---|---|
IndexError w create_polygon | Sprawdź, czy wszystkie indeksy mieszczą się w range(len(mesh.control_points)). Indeksy są zerowo‑indeksowane. |
| Eksport siatki z zerową liczbą wierzchołków | mesh.control_points.append(...) cicho odrzuca wierzchołki, ponieważ właściwość zwraca kopię. Użyj mesh._control_points.append(...) zamiast tego. |
| Liczba wektorów normalnych nie zgadza się z liczbą wierzchołków | Podczas używania MappingMode.CONTROL_POINT + ReferenceMode.DIRECT, normals.data musi mieć dokładnie len(control_points) elementów. |
| Siatka brakująca w zapisanym pliku | Potwierdź, że node.add_entity(mesh) zostało wywołane przed scene.save(). Siatka nie podłączona do żadnego węzła nie jest eksportowana. |
| Nieprawidłowy porządek wiązania (ściana wydaje się niewidoczna) | Kierunek wierzchołków przeciwny do ruchu wskazówek zegara powoduje normalną skierowaną na zewnątrz. Odwróć kolejność indeksów w create_polygon aby to odwrócić. |
polygon_count zwraca 0 | polygon_count odczytuje tę samą listę co polygons. Jeśli create_polygon nie zostało wywołane, lista jest pusta. |
| Normalne wydają się niepoprawne w przeglądarce | Upewnij się, że wszystkie wektory normalne mają długość jednostkową. Oblicz za pomocą n / abs(n) lub przekaż wstępnie znormalizowane wartości. |
Najczęściej zadawane pytania
Jaka jest różnica między Vector3 a Vector4 dla punktów kontrolnych?
control_points przechowuje Vector4 obiekty. Ten w komponent jest współrzędną jednorodną: użyj w=1 do pozycji wierzchołków oraz w=0 do wektorów kierunkowych, takich jak normalne. Vector3 jest używany do przekształceń (translacja, skalowanie), ale nie do przechowywania geometrii.
Czy mogę zbudować siatkę z czworokątów zamiast trójkątów?
Tak. Wywołaj mesh.create_polygon(0, 1, 2, 3) z czterema indeksami, aby zdefiniować czworokąt. Niektóre formaty docelowe zapisu (STL, 3MF) wymagają trójkątów i automatycznie triangulują czworokąty. glTF i COLLADA zachowują czworokąty.
Jak dodać współrzędne UV?
Użyj mesh.create_element_uv(TextureMapping.DIFFUSE, MappingMode.POLYGON_VERTEX) aby utworzyć a VertexElementUV dla kanału dyfuzyjnego, a następnie wypełnij jego data listę z Vector4 wpisy. Współrzędne UV używają x i y; z i w zwykle wynoszą 0. Pierwszy argument musi być a TextureMapping stałą (np., TextureMapping.DIFFUSE) określająca, do którego slotu tekstury należy warstwa UV.
Czy mesh potrzebuje normalnych, aby poprawnie eksportować?
Nie. Normalne są opcjonalne. Jeśli zostaną pominięte, większość przeglądarek oblicza normalne per‑face na podstawie kolejności wierzchołków wielokąta. Dodanie explicite normalnych per‑vertex zapewnia płynniejsze cieniowanie.
Czy mogę dodać wiele meshów do jednego węzła?
Tak. Wywołaj node.add_entity(mesh) wiele razy. Każde wywołanie dodaje nową jednostkę do node.entities. Niektóre formaty mogą spłaszczyć wiele jednostek w jedną podczas eksportu.
Jak triangulować mesh z mieszanymi typami wielokątów?
Wywołaj mesh.triangulate() aby przekształcić wszystkie czworokąty i N‑kąty w trójkąty w miejscu. Jest to przydatne przed zapisem do formatów, które obsługują wyłącznie trójkąty.