Hoe een 3D‑mesh te bouwen met Aspose.3D in Python

Hoe een 3D‑mesh te bouwen met Aspose.3D in Python

Aspose.3D FOSS voor Python stelt je in staat om 3D‑geometrie volledig in code te bouwen: geen extern modelleringshulpmiddel nodig. Je maakt een Mesh, vult deze met vertexposities (control_points) en vlakdefinities (polygons), voegt optionele vertexattributen toe zoals normalen, en slaat vervolgens de scène 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-foss

Controleer 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 scène en een knooppunt

Elke mesh moet zich binnen een scene graph bevinden. Maak een Scene en voeg een benoemde Node toe om de mesh vast te houden:

from aspose.threed import Scene

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

De knooppuntnaam wordt bewaard in het geëxporteerde bestand en is handig voor debugging en later ophalen 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 polygonen. Je vult hem in de volgende stappen.


Stap 4: Controlepunten toevoegen (Vertices)

Controlepunten zijn de vertexposities. 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 retourneert een kopie van de interne vertex‑lijst (de getter voert list(self._control_points) uit). Het aanroepen van mesh.control_points.append(v) voegt toe aan de kopie, niet aan de 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 in een toekomstige versie van de bibliotheek veranderen.


Stap 5: Polygonvlakken maken

Definieer de vlaktopologie met vertexindices. Geef vertexindices door aan create_polygon(). Drie indices produceren een driehoek; vier produceren 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).

Indices moeten geldige posities zijn in control_points (0-gebaseerd, binnen bereik). Winding order is tegen de klok in voor outward-facing normals.


Stap 6: Vertexnormals toevoegen

Vertexnormals worden opgeslagen als een VertexElement die aan het mesh is gekoppeld. 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 normaalgegevens worden gelezen in dezelfde volgorde als de controlepunten (geen extra indexbuffer).

Normale vectoren gebruiken FVector4(x, y, z, w) met w=0 om een richting aan te geven in plaats van een positie. FVector4 is een enkelprecisie float‑vector; vertex‑attribuutgegevens in VertexElementFVector‑subklassen gebruiken dit type.


Stap 7: Koppel het Mesh aan de Node en sla op

Voeg het mesh toe aan de node, 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

ProbleemOplossing
IndexError in create_polygonControleer of alle indexen binnen range(len(mesh.control_points)) liggen. Indexen zijn 0-gebaseerd.
Mesh exporteert met nul verticesmesh.control_points.append(...) verwijdert stilletjes vertices omdat de eigenschap een kopie retourneert. Gebruik in plaats daarvan mesh._control_points.append(...).
Aantal normalen komt niet overeen met aantal verticesBij gebruik van MappingMode.CONTROL_POINT + ReferenceMode.DIRECT moet normals.data precies len(control_points) items bevatten.
Mesh ontbreekt in opgeslagen bestandBevestig dat node.add_entity(mesh) is aangeroepen vóór scene.save(). Een mesh die niet aan een node is gekoppeld, wordt niet geëxporteerd.
Verkeerde windingvolgorde (vlak lijkt onzichtbaar)Een tegen de klok in vertexvolgorde produceert een naar buiten gerichte normaal. Keer de indexvolgorde in create_polygon om deze te draaien.
polygon_count returns 0polygon_count leest dezelfde lijst als polygons. Als create_polygon niet is aangeroepen, is de lijst leeg.
Normalen lijken onjuist in viewerZorg ervoor dat alle normaalvectoren een eenheidslengte hebben. Bereken ze 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 Vector4 objecten op. Het w-component is de homogene coördinaat: gebruik w=1 voor vertexposities en w=0 voor richtingsvectoren zoals normalen. Vector3 wordt gebruikt voor transformaties (vertaling, schaal), maar niet voor geometrieopslag.

Kan ik een mesh bouwen met quads in plaats van driehoeken?

Ja. Roep mesh.create_polygon(0, 1, 2, 3) aan met vier indexen om een quad te definiëren. Sommige opslagdoelen (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 te maken, en vul vervolgens de 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 zijn (bijv. TextureMapping.DIFFUSE) die aangeeft tot welke textuursleuf de UV‑laag behoort.

Moet de mesh normaalvectoren hebben om correct te exporteren?

Nee. Normals zijn optioneel. Indien weggelaten, berekenen de meeste viewers per-face normals uit de polygon winding order. Het toevoegen van expliciete per-vertex normals produceert gladdere shading.

Kan ik meerdere meshes aan één knooppunt toevoegen?

Ja. Roep node.add_entity(mesh) meerdere keren aan. Elke oproep voegt een nieuwe entiteit toe aan node.entities. Sommige formaten kunnen meerdere entiteiten bij export samenvoegen tot één.

Hoe trianguleer ik een mesh met gemengde polygoontypen?

Roep mesh.triangulate() aan om alle quads en N‑gons ter plaatse naar driehoeken te converteren. Dit is handig vóór het opslaan naar formaten die alleen driehoeken ondersteunen.

 Nederlands