Hoe een 3D‑mesh te bouwen met Aspose.3D in Python
Aspose.3D FOSS voor Python stelt je in staat om 3D-geometry volledig in code te bouwen: geen extern modelleringshulpmiddel vereist. Je maakt een Mesh, vul het met vertex positions (control_points) en face definitions (polygons), voeg optionele vertex-attributen toe zoals normals, en sla vervolgens de scene op in elk ondersteund formaat.
Stapsgewijze handleiding
Stap 1: Installeer het pakket
Installeer Aspose.3D FOSS vanaf PyPI. Er zijn geen native extensies of compiler-toolchain vereist.
pip install aspose-3d-fossControleer de installatie:
from aspose.threed import Scene
print("Aspose.3D FOSS ready")Ondersteunde Python-versies: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.
Stap 2: Maak een Scene en een Node
Elke mesh moet zich binnen een scene graph bevinden. Maak een Scene en voeg een benoemde Node toe om de mesh te bevatten:
from aspose.threed import Scene
scene = Scene()
node = scene.root_node.create_child_node("triangle")De node-naam wordt bewaard in het geëxporteerde bestand en is nuttig voor debugging en latere opvraging via node.get_child("triangle").
Stap 3: Maak een Mesh‑object
Instantieer een Mesh met een optionele beschrijvende naam:
from aspose.threed.entities import Mesh
mesh = Mesh("triangle")De mesh is aanvankelijk leeg: geen vertices, geen polygons. Je vult deze in de volgende stappen.
Stap 4: Voeg Control Points (Vertices) toe
Control points zijn de vertex positions. Elke vertex wordt opgeslagen als een Vector4(x, y, z, w) waarbij w=1 een punt in de 3D-ruimte aangeeft:
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)}")Belangrijk: mesh.control_points geeft een kopie van de interne vertexlijst (de getter voert list(self._control_points)). Aanroepen mesh.control_points.append(v) voegt toe aan de kopie, niet aan het mesh, waardoor de vertex stilletjes wordt weggegooid. Gebruik altijd mesh._control_points.append(v) om vertices toe te voegen. Toegang tot private state via _control_points is een bekende workaround; de interface kan veranderen in een toekomstige versie van de bibliotheek.
Stap 5: Maak Polygon‑faces
Definieer de topologie van het vlak met vertex-indexen. Geef vertex-indexen door aan create_polygon(). Drie indexen vormen een driehoek; vier vormen een quad:
##Triangle: connect vertices 0 → 1 → 2
mesh.create_polygon(0, 1, 2)
print(f"Polygon count: {mesh.polygon_count}")Voor een quad-mesh zou je vier indexen doorgeven: mesh.create_polygon(0, 1, 2, 3).
Indexen moeten geldige posities zijn in control_points (0-gebaseerd, binnen bereik). De windingvolgorde is tegen de klok in voor naar buiten gerichte normaalvectoren.
Stap 6: Vertex Normals toevoegen
Vertex-normaalvectoren worden opgeslagen als een VertexElement gekoppeld aan de mesh. Gebruik mesh.create_element() met VertexElementType.NORMAL, MappingMode.CONTROL_POINT, en 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 betekent één normaal per vertex. ReferenceMode.DIRECT betekent dat de normaaldata wordt gelezen in dezelfde volgorde als de controlepunten (geen extra indexbuffer).
Normaalvectoren gebruiken FVector4(x, y, z, w) met w=0 om een richting aan te geven in plaats van een positie. FVector4 is een single-precision float vector; vertex-attribuutgegevens in VertexElementFVector subklassen gebruiken dit type.
Stap 7: De mesh aan de node koppelen en opslaan
Voeg de mesh toe aan de node en sla vervolgens de scène op:
node.add_entity(mesh)
scene.save("triangle.gltf")
print("Saved triangle.gltf")Het volledige werkende script (alle stappen gecombineerd):
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")Veelvoorkomende problemen
| Probleem | Oplossing |
|---|---|
IndexError in create_polygon | Controleer dat alle indexen binnen range(len(mesh.control_points)). Indexen zijn 0-gebaseerd. |
| Mesh exporteert met nul vertices | mesh.control_points.append(...) verwijdert stilzwijgend vertices omdat de eigenschap een kopie retourneert. Gebruik mesh._control_points.append(...) in plaats daarvan. |
| Normals count komt niet overeen met vertex count | Bij gebruik van MappingMode.CONTROL_POINT + ReferenceMode.DIRECT, normals.data moet precies len(control_points) items. |
| Mesh ontbreekt in opgeslagen bestand | Bevestig dat node.add_entity(mesh) werd aangeroepen vóór scene.save(). Een mesh die niet aan een node is gekoppeld, wordt niet geëxporteerd. |
| Verkeerde windingvolgorde (vlak lijkt onzichtbaar) | Tegen de klok in vertexvolgorde produceert een naar buiten gerichte normal. Keer de indexvolgorde om in create_polygon om het om te keren. |
polygon_count geeft 0 terug | polygon_count leest dezelfde lijst als polygons. Als create_polygon werd niet aangeroepen, de lijst is leeg. |
| Normalen lijken onjuist in de viewer | Zorg ervoor dat alle normaalvectoren een eenheidslengte hebben. Bereken met n / abs(n) of geef vooraf genormaliseerde waarden door. |
Veelgestelde vragen
Wat is het verschil tussen Vector3 en Vector4 voor controlepunten?
control_points slaat op Vector4 objecten. De w component is de homogene coördinaat: gebruik w=1 voor vertexposities en w=0 voor richtingsvectoren zoals normalen. Vector3 wordt gebruikt voor transformaties (translatie, schaal) maar niet voor geometrieopslag.
Kan ik een mesh bouwen met quads in plaats van driehoeken?
Ja. Roep aan mesh.create_polygon(0, 1, 2, 3) met vier indexen om een quad te definiëren. Sommige opslagformaten (STL, 3MF) vereisen driehoeken en zullen quads automatisch trianguleren. glTF en COLLADA behouden quads.
Hoe voeg ik UV‑coördinaten toe?
Gebruik mesh.create_element_uv(TextureMapping.DIFFUSE, MappingMode.POLYGON_VERTEX) om een VertexElementUV voor het diffuse kanaal, vul vervolgens zijn data lijst met Vector4 items. UV-coördinaten gebruiken x en y; z en w zijn meestal 0. Het eerste argument moet een TextureMapping constante (bijv., TextureMapping.DIFFUSE) die aangeeft tot welke textuursleuf de UV-laag behoort.
Heeft het mesh normale nodig om correct te exporteren?
Nee. Normals zijn optioneel. Indien weggelaten, berekenen de meeste viewers per‑vlak normals op basis van de winding order van de polygonen. Het toevoegen van expliciete per‑vertex normals zorgt voor een vloeiendere shading.
Kan ik meerdere meshes aan één node toevoegen?
Ja. Roep node.add_entity(mesh) meerdere keren. Elke oproep voegt een nieuw object toe aan node.entities. Sommige formaten kunnen meerdere objecten bij export samenvoegen tot één.
Hoe trianguleer ik een mesh met gemengde polygon-typen?
Roep mesh.triangulate() om alle quads en N-gons ter plaatse om te zetten naar driehoeken. Dit is handig vóór het opslaan naar formaten die alleen driehoeken ondersteunen.