Com crear una malla 3D amb Aspose.3D a Python

Com crear una malla 3D amb Aspose.3D a Python

Aspose.3D FOSS per a Python et permet crear geometria 3D completament amb codi: no cal cap eina de modelatge externa. Crees un Mesh, l’omples amb posicions de vèrtex (control_points) i definicions de cares (polygons), adjuntes atributs de vèrtex opcionals com ara normals, i després guardes l’escena en qualsevol format compatible.

Guia pas a pas

Pas 1: Instal·la el paquet

Instal·la Aspose.3D FOSS des de PyPI. No es requereixen extensions natives ni cadena d’eines del compilador.

pip install aspose-3d-foss

Verifiqueu la instal·lació:

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

Versions de Python compatibles: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.


Pas 2: Crea una Escena i un Node

Cada malla ha d’estar dins d’un gràfic d’escena. Crea un Scene i afegeix un Node amb nom per contenir la malla:

from aspose.threed import Scene

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

El nom del node es conserva al fitxer exportat i és útil per a la depuració i la recuperació posterior mitjançant node.get_child("triangle").


Pas 3: Crea un objecte Mesh

Instancia una Mesh amb un nom descriptiu opcional:

from aspose.threed.entities import Mesh

mesh = Mesh("triangle")

La malla està inicialment buida: sense vèrtexs, sense polígons. La omples en els passos següents.


Pas 4: Afegeix punts de control (Vèrtexs)

Els punts de control són les posicions dels vèrtexs. Cada vèrtex s’emmagatzema com a Vector4(x, y, z, w) on w=1 indica un punt en l’espai 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)}")

Important: mesh.control_points retorna una còpia de la llista interna de vèrtexs (el getter executa list(self._control_points)). En cridar mesh.control_points.append(v) s’afegeix a la còpia, no a la malla, de manera que el vèrtex es descarta silenciosament. Utilitzeu sempre mesh._control_points.append(v) per afegir vèrtexs. Accedir a l’estat privat mitjançant _control_points és una solució alternativa coneguda; la interfície pot canviar en una futura versió de la biblioteca.


Pas 5: Crea cares de polígon

Definiu la topologia de la cara mitjançant índexs de vèrtex. Passeu els índexs de vèrtex a create_polygon(). Tres índexs produeixen un triangle; quatre produeixen un quad:

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

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

Per a una malla de quàdrups hauries de passar quatre índexs: mesh.create_polygon(0, 1, 2, 3).

Els índexs han de ser posicions vàlides a control_points (basat en zero, dins del rang). L’ordre d’enrotllament és en sentit antihorari per a normals orientades cap a fora.


Pas 6: Afegeix normals de vèrtex

Les normals dels vèrtexs s’emmagatzemen com a VertexElement adjuntat a la malla. Utilitzeu mesh.create_element() amb 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 significa una normal per vèrtex. ReferenceMode.DIRECT significa que les dades de normals es llegeixen en el mateix ordre que els punts de control (sense cap buffer d’índex addicional).

Els vectors normals utilitzen FVector4(x, y, z, w) amb w=0 per indicar una direcció en lloc d’una posició. FVector4 és un vector de coma flotant de precisió simple; les dades d’atribut de vèrtex en les subclasses VertexElementFVector fan servir aquest tipus.


Pas 7: Adjunta la malla al node i desa

Afegeix la malla al node, després desa l’escena:

node.add_entity(mesh)

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

El script complet que funciona (tots els passos combinats):

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

Problemes comuns

IssueResolution
IndexError a create_polygonVerifiqueu que tots els índexs estiguin dins de range(len(mesh.control_points)). Els índexs comencen a 0.
Exportació de malla amb zero vèrtexsmesh.control_points.append(...) descarta silenciosament els vèrtexs perquè la propietat retorna una còpia. Useu mesh._control_points.append(...) en canvi.
El recompte de normals no coincideix amb el recompte de vèrtexsQuan s’utilitza MappingMode.CONTROL_POINT + ReferenceMode.DIRECT, normals.data ha de tenir exactament len(control_points) entrades.
Malla absent del fitxer desatConfirmeu que node.add_entity(mesh) s’ha cridat abans de scene.save(). Una malla que no està adjuntada a cap node no s’exporta.
Ordre d’enrotllament incorrecte (la cara apareix invisible)L’ordre de vèrtexs en sentit antihorari produeix una normal cap a fora. Inverteix l’ordre dels índexs a create_polygon per girar-la.
polygon_count retorna 0polygon_count llegeix la mateixa llista que polygons. Si create_polygon no s’ha cridat, la llista és buida.
Les normals apareixen incorrectes al visualitzadorAssegureu-vos que tots els vectors normals tinguin longitud unitària. Calculeu-los amb n / abs(n) o passeu valors pre-normalitzats.

Preguntes freqüents

Quina és la diferència entre Vector3 i Vector4 per als punts de control?

control_points emmagatzema objectes Vector4. El component w és la coordenada homogènia: utilitzeu w=1 per a les posicions dels vèrtexs i w=0 per a vectors de direcció com ara normals. Vector3 s’utilitza per a transformacions (traducció, escala) però no per a l’emmagatzematge de geometria.

Puc crear una malla amb quads en lloc de triangles?

Sí. Crida mesh.create_polygon(0, 1, 2, 3) amb quatre índexs per definir un quad. Alguns destinacions de desament (STL, 3MF) requereixen triangles i triangul·laran els quads automàticament. glTF i COLLADA conserven els quads.

Com puc afegir coordenades UV?

Utilitzeu mesh.create_element_uv(TextureMapping.DIFFUSE, MappingMode.POLYGON_VERTEX) per crear un VertexElementUV per al canal difús, i després ompliu la seva llista data amb Vector4 entrades. Les coordenades UV utilitzen x i y; z i w són típicament 0. El primer argument ha de ser una constant TextureMapping (p. ex., TextureMapping.DIFFUSE) que identifica a quin slot de textura pertany la capa UV.

La malla necessita normals per exportar correctament?

No. Les normals són opcionals. Si s’ometen, la majoria de visualitzadors calculen les normals per cara a partir de l’ordre de gir del polígon. Afegir normals per vèrtex explícites produeix una ombreig més suau.

Puc afegir diverses malles a un node?

Sí. Crida node.add_entity(mesh) diverses vegades. Cada crida afegeix una nova entitat a node.entities. Alguns formats poden aplanar diverses entitats en una sola en l’exportació.

Com puc triangul·lar una malla amb tipus de polígons mixtes?

Crida mesh.triangulate() per convertir tots els quads i N-gons en triangles in situ. Això és útil abans de desar a formats que només admeten triangles.

 Català