Come costruire una mesh 3D con Aspose.3D in Python

Come costruire una mesh 3D con Aspose.3D in Python

Aspose.3D FOSS per Python ti consente di costruire geometria 3D interamente in codice: non è necessario alcun strumento di modellazione esterno. Crei un Mesh, popolalo con le posizioni dei vertici (control_points) e le definizioni delle facce (polygons) , salva la scena in qualsiasi formato supportato.

Guida passo-passo

Passo 1: Installa il pacchetto

Installa Aspose.3D FOSS da PyPI. Non sono richieste estensioni native né toolchain del compilatore.

pip install aspose-3d-foss

Verifica l’installazione:

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

Versioni Python supportate: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.


Passo 2: Crea una Scena e un Nodo

Ogni mesh deve trovarsi all’interno di un grafo di scena. Crea un Scene e aggiungi un/a chiamato/a Node per contenere la mesh:

from aspose.threed import Scene

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

Il nome del nodo viene conservato nel file esportato ed è utile per il debug e per il successivo recupero tramite node.get_child("triangle").


Passo 3: Crea un Oggetto Mesh

Istanzia un/a Mesh con un nome descrittivo opzionale:

from aspose.threed.entities import Mesh

mesh = Mesh("triangle")

Il mesh è inizialmente vuoto: nessun vertice, nessun poligono. Lo popoli nei passaggi seguenti.


Passo 4: Aggiungi i Punti di Controllo (Vertici)

I punti di controllo sono le posizioni dei vertici. Ogni vertice è memorizzato come un/a Vector4(x, y, z, w) dove w=1 indica un punto nello spazio 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)}")

Importante: mesh.control_points restituisce un/a copia della lista interna dei vertici (il getter esegue list(self._control_points)). Chiamando mesh.control_points.append(v) aggiunge alla copia, non alla mesh, quindi il vertice viene scartato silenziosamente. Usa sempre mesh._control_points.append(v) per aggiungere vertici. Accedere allo stato privato tramite _control_points è una soluzione alternativa nota; l’interfaccia potrebbe cambiare in una futura versione della libreria.


Passo 5: Crea le Facce Poligonali

Definisci la topologia delle facce usando gli indici dei vertici. Passa gli indici dei vertici a create_polygon().Tre indici producono un triangolo; quattro producono un quadrilatero:

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

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

Per una mesh a quadrilatero dovresti passare quattro indici: mesh.create_polygon(0, 1, 2, 3).

Gli indici devono essere posizioni valide in control_points (basato su zero, entro l’intervallo). L’ordine di avvolgimento è in senso antiorario per le normali rivolte verso l’esterno.


Passo 6: Aggiungi le normali dei vertici

Le normali dei vertici sono memorizzate come un VertexElement allegato alla mesh. Usa mesh.create_element() con VertexElementType.NORMAL, MappingMode.CONTROL_POINT, e 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 significa una normale per vertice. ReferenceMode.DIRECT significa che i dati delle normali sono letti nello stesso ordine dei punti di controllo (nessun buffer di indice aggiuntivo).

I vettori normali usano FVector4(x, y, z, w) con w=0 per indicare una direzione piuttosto che una posizione. FVector4 è un vettore di float a precisione singola; dati di attributi di vertice in VertexElementFVector le sottoclassi usano questo tipo.


Passo 7: Collega la Mesh al Nodo e Salva

Aggiungi la mesh al nodo, quindi salva la scena:

node.add_entity(mesh)

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

Lo script completo funzionante (tutti i passaggi combinati):

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

Problemi comuni

ProblemaRisoluzione
IndexError in create_polygonVerifica che tutti gli indici siano entro range(len(mesh.control_points)). Gli indici sono a base zero.
Mesh esportata con zero verticimesh.control_points.append(...) scarta silenziosamente i vertici perché la proprietà restituisce una copia. Usa mesh._control_points.append(...) invece.
Il conteggio delle normali non corrisponde al conteggio dei verticiQuando si utilizza MappingMode.CONTROL_POINT + ReferenceMode.DIRECT, normals.data deve avere esattamente len(control_points) voci.
Mesh mancante dal file salvatoConferma che node.add_entity(mesh) è stato chiamato prima di scene.save(). Una mesh non collegata a nessun nodo non viene esportata.
Ordine di avvolgimento errato (la faccia appare invisibile)L’ordine dei vertici in senso antiorario produce una normale rivolta verso l’esterno. Inverti l’ordine degli indici in create_polygon per capovolgerlo.
polygon_count restituisce 0polygon_count legge la stessa lista come polygons. Se create_polygon non è stato chiamato, l’elenco è vuoto.
Le normali appaiono errate nel visualizzatoreAssicurati che tutti i vettori normali siano di lunghezza unità. Calcola con n / abs(n) oppure passa valori pre-normalizzati.

Domande frequenti

Qual è la differenza tra Vector3 e Vector4 per i punti di controllo?

control_points memorizza Vector4 oggetti. Il w componente è la coordinata omogenea: usa w=1 per le posizioni dei vertici e w=0 per i vettori direzionali come le normali. Vector3 è usato per le trasformazioni (traslazione, scala) ma non per l’archiviazione della geometria.

Posso creare una mesh con quad invece di triangoli?

Sì. Chiama mesh.create_polygon(0, 1, 2, 3) con quattro indici per definire un quadrilatero. Alcuni formati di salvataggio (STL, 3MF) richiedono triangoli e triangoleranno automaticamente i quadrilateri. glTF e COLLADA preservano i quadrilateri.

Come aggiungo le coordinate UV?

Usa mesh.create_element_uv(TextureMapping.DIFFUSE, MappingMode.POLYGON_VERTEX) per creare un VertexElementUV per il canale diffuso, quindi popola il suo data lista con Vector4 voci. Le coordinate UV usano x e y; z e w sono tipicamente 0. Il primo argomento deve essere un TextureMapping costante (ad es., TextureMapping.DIFFUSE) che identifica a quale slot di texture appartiene lo strato UV.

La mesh ha bisogno di normali per esportare correttamente?

No. Le normali sono opzionali. Se omesse, la maggior parte dei visualizzatori calcola le normali per faccia dall’ordine di winding del poligono. Aggiungere normali per vertice esplicite produce un’ombreggiatura più fluida.

Posso aggiungere più mesh a un nodo?

Sì. Chiama node.add_entity(mesh) più volte. Ogni chiamata aggiunge una nuova entità a node.entities. Alcuni formati possono appiattire più entità in una sola durante l’esportazione.

Come triangolare una mesh con tipi di poligono misti?

Chiama mesh.triangulate() per convertire tutti i quadri e gli N-gon in triangoli in loco. Questo è utile prima di salvare in formati che supportano solo triangoli.

 Italiano