Wie man ein 3D-Mesh mit Aspose.3D in Python erstellt

Wie man ein 3D-Mesh mit Aspose.3D in Python erstellt

Aspose.3D FOSS für Python ermöglicht es Ihnen, 3D-Geometrie vollständig im Code zu erstellen: kein externes Modellierungswerkzeug erforderlich. Sie erstellen ein Mesh, füllen es mit Scheitelpunktpositionen (control_points) und Flächendefinitionen (polygons), hängen optionale Vertex-Attribute wie Normalen an und speichern dann die Szene in ein beliebiges unterstütztes Format.

Schritt-für-Schritt-Anleitung

Schritt 1: Paket installieren

Installieren Sie Aspose.3D FOSS von PyPI. Keine nativen Erweiterungen oder Compiler‑Toolchain sind erforderlich.

pip install aspose-3d-foss

Installation überprüfen:

from aspose.threed import Scene
print("Aspose.3D FOSS ready")

Unterstützte Python-Versionen: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.


Schritt 2: Erstelle eine Szene und einen Knoten

Jedes Mesh muss innerhalb eines Szenengraphen leben. Erstelle ein Scene und füge ein benanntes Node hinzu, um das Mesh zu halten:

from aspose.threed import Scene

scene = Scene()
node = scene.root_node.create_child_node("triangle")

Der Knotenname wird in der exportierten Datei beibehalten und ist nützlich für das Debuggen und den späteren Abruf über node.get_child("triangle").


Schritt 3: Mesh-Objekt erstellen

Instanziieren Sie ein Mesh mit einem optionalen beschreibenden Namen:

from aspose.threed.entities import Mesh

mesh = Mesh("triangle")

Das Mesh ist zunächst leer: keine Scheitelpunkte, keine Polygone. Sie füllen es in den folgenden Schritten.


Schritt 4: Kontrollpunkte hinzufügen (Scheitelpunkte)

Steuerpunkte sind die Scheitelpunktpositionen. Jeder Scheitelpunkt wird als Vector4(x, y, z, w) gespeichert, wobei w=1 einen Punkt im 3D‑Raum bezeichnet:

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

Wichtig: mesh.control_points gibt eine Kopie der internen Vertex‑Liste zurück (der Getter führt list(self._control_points) aus). Der Aufruf von mesh.control_points.append(v) fügt zur Kopie hinzu, nicht zum Mesh, sodass der Vertex stillschweigend verworfen wird. Verwenden Sie immer mesh._control_points.append(v), um Vertices hinzuzufügen. Der Zugriff auf privaten Zustand über _control_points ist ein bekannter Workaround; die Schnittstelle kann sich in einer zukünftigen Version der Bibliothek ändern.


Schritt 5: Polygonflächen erstellen

Definieren Sie die Flächentopologie mithilfe von Scheitelpunktindizes. Übergeben Sie die Scheitelpunktindizes an create_polygon(). Drei Indizes erzeugen ein Dreieck; vier erzeugen ein Viereck:

##Triangle: connect vertices 0 → 1 → 2
mesh.create_polygon(0, 1, 2)

print(f"Polygon count: {mesh.polygon_count}")

Für ein Quad‑Mesh würden Sie vier Indizes übergeben: mesh.create_polygon(0, 1, 2, 3).

Indizes müssen gültige Positionen in control_points sein (0‑basiert, innerhalb des Bereichs). Die Windungsreihenfolge ist gegen den Uhrzeigersinn für nach außen gerichtete Normalen.


Schritt 6: Vertex‑Normalen hinzufügen

Vertex-Normalen werden als VertexElement am Mesh gespeichert. Verwenden Sie mesh.create_element() mit VertexElementType.NORMAL, MappingMode.CONTROL_POINT und 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 bedeutet ein Normalvektor pro Scheitelpunkt. ReferenceMode.DIRECT bedeutet, dass die Normaldaten in derselben Reihenfolge wie die Kontrollpunkte gelesen werden (kein zusätzlicher Indexpuffer).

Normalenvektoren verwenden FVector4(x, y, z, w) mit w=0, um eine Richtung statt einer Position anzugeben. FVector4 ist ein Single‑Precision‑Float‑Vektor; Vertex‑Attributdaten in VertexElementFVector‑Unterklassen verwenden diesen Typ.


Schritt 7: Das Mesh an den Knoten anhängen und speichern

Fügen Sie das Mesh dem Knoten hinzu, dann speichern Sie die Szene:

node.add_entity(mesh)

scene.save("triangle.gltf")
print("Saved triangle.gltf")

Das vollständige funktionierende Skript (alle Schritte kombiniert):

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

Häufige Probleme

ProblemLösung
IndexError in create_polygonStellen Sie sicher, dass alle Indizes innerhalb von range(len(mesh.control_points)) liegen. Indizes sind 0‑basiert.
Mesh-Export mit null Verticesmesh.control_points.append(...) verwirft stillschweigend Vertices, weil die Eigenschaft eine Kopie zurückgibt. Verwenden Sie stattdessen mesh._control_points.append(...).
Anzahl der Normalen stimmt nicht mit der Vertex‑Anzahl übereinBeim Einsatz von MappingMode.CONTROL_POINT + ReferenceMode.DIRECT muss normals.data genau len(control_points) Einträge enthalten.
Mesh fehlt in der gespeicherten DateiStellen Sie sicher, dass node.add_entity(mesh) vor scene.save() aufgerufen wurde. Ein Mesh, das keinem Knoten zugeordnet ist, wird nicht exportiert.
Falsche Windungsreihenfolge (Fläche erscheint unsichtbar)Eine gegen den Uhrzeigersinn verlaufende Vertex‑Reihenfolge erzeugt eine nach außen gerichtete Normale. Kehren Sie die Indexreihenfolge in create_polygon um, um sie zu invertieren.
polygon_count returns 0polygon_count liest dieselbe Liste wie polygons. Wenn create_polygon nicht aufgerufen wurde, ist die Liste leer.
Normalen erscheinen im Viewer falschStellen Sie sicher, dass alle Normalenvektoren eine Länge von 1 haben. Berechnen Sie sie mit n / abs(n) oder übergeben Sie vorab normalisierte Werte.

Häufig gestellte Fragen

Was ist der Unterschied zwischen Vector3 und Vector4 für Kontrollpunkte?

control_points speichert Vector4 Objekte. Die w Komponente ist die homogene Koordinate: Verwenden Sie w=1 für Scheitelpunktpositionen und w=0 für Richtungsvektoren wie Normalen. Vector3 wird für Transformationen (Translation, Skalierung) verwendet, jedoch nicht für die Geometriespeicherung.

Kann ich ein Mesh mit Quads anstelle von Dreiecken erstellen?

Ja. Rufen Sie mesh.create_polygon(0, 1, 2, 3) mit vier Indizes auf, um ein Quad zu definieren. Einige Speicherziele (STL, 3MF) benötigen Dreiecke und triangulieren Quads automatisch. glTF und COLLADA erhalten Quads.

Wie füge ich UV‑Koordinaten hinzu?

Verwenden Sie mesh.create_element_uv(TextureMapping.DIFFUSE, MappingMode.POLYGON_VERTEX), um ein VertexElementUV für den Diffuse‑Kanal zu erstellen, und füllen Sie dann seine data‑Liste mit Vector4‑Einträgen. UV‑Koordinaten verwenden x und y; z und w sind typischerweise 0. Das erste Argument muss eine TextureMapping‑Konstante sein (z. B. TextureMapping.DIFFUSE), die angibt, welchem Texturslot die UV‑Ebene zugeordnet ist.

Benötigt das mesh Normalen, um korrekt exportiert zu werden?

Nein. Normalen sind optional. Wenn sie weggelassen werden, berechnen die meisten Viewer per-face normals aus der Polygon‑Windungsreihenfolge. Das Hinzufügen expliziter per-vertex normals erzeugt eine glattere Schattierung.

Kann ich mehrere Meshes zu einem Knoten hinzufügen?

Ja. Rufen Sie node.add_entity(mesh) mehrfach auf. Jeder Aufruf fügt eine neue Entität zu node.entities hinzu. Einige Formate können mehrere Entitäten beim Export zu einer zusammenfassen.

Wie trianguliere ich ein Mesh mit gemischten Polygon‑Typen?

Rufen Sie mesh.triangulate() auf, um alle Vierecke und N‑Gons vor Ort in Dreiecke zu konvertieren. Dies ist nützlich, bevor Sie in Formate speichern, die nur Dreiecke unterstützen.

 Deutsch