Característiques i funcionalitats
Aspose.3D FOSS per a Python ofereix una API completa de gràfic d’escena per a llegir, construir i escriure contingut 3D en diversos formats estàndard de la indústria. Aquesta pàgina documenta cada àrea funcional principal amb exemples de codi Python funcionals que utilitzen l’API real de la biblioteca.
Instal·lació i configuració
Instal·leu la biblioteca des de PyPI amb una sola ordre:
pip install aspose-3d-fossNo es requereixen paquets de sistema addicionals, extensions natives ni cadenes d’eines de compilador. La biblioteca és purament Python i admet Python 3.7 fins a 3.12 a Windows, macOS i Linux.
Per verificar la instal·lació:
from aspose.threed import Scene
scene = Scene()
print("Aspose.3D FOSS installed successfully")
print(f"Root node name: {scene.root_node.name}")Característiques i funcionalitats
Compatibilitat de formats
Aspose.3D FOSS per a Python llegeix i escriu els formats següents:
| Format | Extensió | Llegir | Escriure | Notes |
|---|---|---|---|---|
| Wavefront OBJ | .obj | Sí | Sí | .mtl suport de càrrega de material |
| STL (binari) | .stl | Sí | Sí | Recórrer verificat (39 proves) |
| STL (ASCII) | .stl | Sí | Sí | Recórrer verificat |
| glTF 2.0 | .gltf | Sí | Sí | Graf de l’escena complet conservat |
| GLB (binary glTF) | .glb | Sí | Sí | Contenidor binari d’un sol fitxer |
| COLLADA | .dae | Sí | Sí | Jerarquia d’escena i materials |
| 3MF | .3mf | Sí | Sí | Format de fabricació additiva |
| FBX | .fbx | Parcial | No | Tokenitzador en funcionament; l’analitzador té errors coneguts |
Carregant OBJ amb opcions
ObjLoadOptions controla com s’analitzen els fitxers OBJ:
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions
options = ObjLoadOptions()
options.enable_materials = True # Load accompanying .mtl file
options.flip_coordinate_system = False # Preserve original handedness
options.normalize_normal = True # Normalize vertex normals to unit length
options.scale = 1.0 # Apply a uniform scale factor at load time
scene = Scene()
scene.open("model.obj", options)
print(f"Loaded {len(scene.root_node.child_nodes)} top-level nodes")Desant a STL
StlSaveOptions controla la sortida binària vs. ASCII i altres configuracions específiques d’STL:
from aspose.threed import Scene
from aspose.threed.formats import StlSaveOptions
scene = Scene.from_file("model.obj")
options = StlSaveOptions()
scene.save("output.stl", options)Gràfic d’escena
Tot el contingut 3D s’organitza com un arbre de Node objectes. L’arrel de l’arbre és scene.root_node. Cada node pot contenir nodes fills i portar un Entity (malla, càmera o llum) més un Transform.
Recórrer la jerarquia d’escena
from aspose.threed import Scene
scene = Scene.from_file("model.glb")
def traverse(node, depth=0):
indent = " " * depth
entity_type = type(node.entity).__name__ if node.entity else "none"
print(f"{indent}{node.name} [{entity_type}]")
for child in node.child_nodes:
traverse(child, depth + 1)
traverse(scene.root_node)Construint una escena programàticament
from aspose.threed import Scene, Node, Entity
from aspose.threed.entities import Mesh
from aspose.threed.utilities import Vector3
scene = Scene()
root = scene.root_node
##Create a child node and position it
child = root.create_child_node("my_object")
child.transform.translation = Vector3(1.0, 0.0, 0.0)
child.transform.scaling = Vector3(2.0, 2.0, 2.0)
scene.save("constructed.glb")Examinant GlobalTransform
GlobalTransform proporciona la transformació en l’espai mundial d’un node després d’acumular totes les transformacions dels avantpassats:
from aspose.threed import Scene
scene = Scene.from_file("model.dae")
for node in scene.root_node.child_nodes:
gt = node.global_transform
print(f"Node: {node.name}")
print(f" World translation: {gt.translation}")
print(f" World scale: {gt.scale}")API de Mesh
El Mesh l’entitat dóna accés a les dades geomètriques incloent punts de control (vèrtexs), polígons i elements de vèrtex per a normals, UVs i colors.
Lectura de la geometria de Mesh
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions
options = ObjLoadOptions()
options.enable_materials = True
options.flip_coordinate_system = False
scene = Scene()
scene.open("model.obj", options)
for node in scene.root_node.child_nodes:
if node.entity is None:
continue
mesh = node.entity
print(f"Mesh: {node.name}")
print(f" Vertices: {len(mesh.control_points)}")
print(f" Polygons: {len(mesh.polygons)}")Accés als elements de vèrtex
Els elements de vèrtex contenen dades per vèrtex o per polígon. Els elements més comuns són les normals, les coordenades UV, els colors de vèrtex i els grups d’alissat:
from aspose.threed import Scene
from aspose.threed.entities import VertexElementNormal, VertexElementUV
scene = Scene.from_file("model.obj")
for node in scene.root_node.child_nodes:
if node.entity is None:
continue
mesh = node.entity
# Iterate vertex elements to find normals and UVs
for element in mesh.vertex_elements:
if isinstance(element, VertexElementNormal):
print(f" Normals count: {len(element.data)}")
elif isinstance(element, VertexElementUV):
print(f" UV count: {len(element.data)}")Sistema de materials
Aspose.3D FOSS admet dos tipus de material: LambertMaterial (ombrejat difús) i PhongMaterial (ombrejat especular). Ambdós es carreguen automàticament des de fitxers .mtl quan s’utilitza ObjLoadOptions amb enable_materials = True.
Lectura de materials des d’OBJ
from aspose.threed import Scene
from aspose.threed.shading import LambertMaterial, PhongMaterial
from aspose.threed.formats import ObjLoadOptions
options = ObjLoadOptions()
options.enable_materials = True
scene = Scene()
scene.open("model.obj", options)
for node in scene.root_node.child_nodes:
mat = node.material
if mat is None:
continue
print(f"Node: {node.name}")
if isinstance(mat, PhongMaterial):
print(f" Type: Phong")
print(f" Diffuse: {mat.diffuse_color}")
print(f" Specular: {mat.specular_color}")
elif isinstance(mat, LambertMaterial):
print(f" Type: Lambert")
print(f" Diffuse: {mat.diffuse_color}")Assignació d’un material programàticament
from aspose.threed import Scene, Node
from aspose.threed.shading import PhongMaterial
from aspose.threed.utilities import Vector3
scene = Scene.from_file("model.glb")
material = PhongMaterial()
material.diffuse_color = Vector3(0.8, 0.2, 0.2) # Red diffuse
material.specular_color = Vector3(1.0, 1.0, 1.0) # White specular
##Apply to the first mesh node
for node in scene.root_node.child_nodes:
if node.entity is not None:
node.material = material
break
scene.save("recolored.glb")Utilitats matemàtiques
El aspose.threed.utilities el mòdul proporciona tots els tipus matemàtics geomètrics necessaris per a la construcció i inspecció d’escenes.
| Classe | Propòsit |
|---|---|
Vector2 | 2D floating-point vector (UV coordinates) |
Vector3 | 3D double-precision vector (positions, normals) |
Vector4 | 4D double-precision vector (homogeneous coordinates) |
FVector3 | 3D single-precision vector (compact storage) |
Quaternion | Representació de rotació sense bloqueig de gimbal |
Matrix4 | 4×4 transformation matrix |
BoundingBox | Caixa delimitadora alineada amb els eixos amb cantonades min/max |
Treballant amb transformacions
from aspose.threed.utilities import Vector3, Quaternion, Matrix4
import math
##Build a rotation quaternion from axis-angle
axis = Vector3(0.0, 1.0, 0.0) # Y-axis
angle_rad = math.radians(45.0)
q = Quaternion.from_angle_axis(angle_rad, axis)
print(f"Quaternion: x={q.x:.4f} y={q.y:.4f} z={q.z:.4f} w={q.w:.4f}")
##Convert to rotation matrix
mat = q.to_matrix()
print(f"Rotation matrix row 0: {mat[0, 0]:.4f} {mat[0, 1]:.4f} {mat[0, 2]:.4f}")Càlcul d’una caixa delimitadora
from aspose.threed import Scene
scene = Scene.from_file("model.stl")
# NOTE: mesh.get_bounding_box() is a stub — it always returns an empty BoundingBox()
# regardless of geometry. Compute bounds manually from control_points:
for node in scene.root_node.child_nodes:
if node.entity is None:
continue
mesh = node.entity
pts = mesh.control_points # returns a copy of the vertex list
if not pts:
continue
xs = [p.x for p in pts]
ys = [p.y for p in pts]
zs = [p.z for p in pts]
print(f"Mesh: {node.name}")
print(f" Min: ({min(xs):.3f}, {min(ys):.3f}, {min(zs):.3f})")
print(f" Max: ({max(xs):.3f}, {max(ys):.3f}, {max(zs):.3f})")Animació
Aspose.3D FOSS proporciona un model d’animació basat en AnimationClip, AnimationNode, KeyFrame, i KeyframeSequence. Les dades d’animació emmagatzemades en fitxers carregats (glTF, COLLADA) són accessibles a través d’aquests objectes.
Lectura de clips d’animació
from aspose.threed import Scene
scene = Scene.from_file("animated.glb")
for clip in scene.animation_clips:
print(f"Clip: {clip.name} ({clip.start:.2f}s – {clip.stop:.2f}s)")
for anim_node in clip.animations:
print(f" Animation node: {anim_node.name}")
for sub in anim_node.sub_animations:
print(f" Sub-animation: {sub.name}")
for bp in anim_node.bind_points:
print(f" Bind point: {bp.name}")Opcions de càrrega i desament
Cada format compatible té una classe d’opcions corresponent que controla el comportament d’anàlisi i serialització.
| Classe | Format | Propietats clau |
|---|---|---|
ObjLoadOptions | OBJ | enable_materials, flip_coordinate_system, normalize_normal, scale |
StlSaveOptions | STL | Mode de sortida binari vs. ASCII |
| (glTF utilitza valors per defecte) | glTF / GLB | El graf de l’escena i els materials es conserven automàticament |
Exemples d’ús
Exemple 1: Conversió de format OBJ a STL
Converteix un fitxer OBJ (amb materials) a STL binari, mostrant les estadístiques de la malla al llarg del procés:
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions
from aspose.threed.formats import StlSaveOptions
##Load OBJ with material support
load_opts = ObjLoadOptions()
load_opts.enable_materials = True
load_opts.flip_coordinate_system = False
load_opts.normalize_normal = True
scene = Scene()
scene.open("input.obj", load_opts)
##Report what was loaded
total_vertices = 0
total_polygons = 0
for node in scene.root_node.child_nodes:
if node.entity is not None:
mesh = node.entity
total_vertices += len(mesh.control_points)
total_polygons += len(mesh.polygons)
print(f" {node.name}: {len(mesh.control_points)} vertices, {len(mesh.polygons)} polygons")
print(f"Total: {total_vertices} vertices, {total_polygons} polygons")
##Save as STL
save_opts = StlSaveOptions()
scene.save("output.stl", save_opts)
print("Saved output.stl")Exemple 2: Empaquetat per lots de glTF a GLB
Torna a desar un directori de fitxers glTF + textures separats com a binaris GLB autònoms:
import os
from aspose.threed import Scene
input_dir = "gltf_files"
output_dir = "glb_files"
os.makedirs(output_dir, exist_ok=True)
for filename in os.listdir(input_dir):
if not filename.endswith(".gltf"):
continue
src = os.path.join(input_dir, filename)
dst = os.path.join(output_dir, filename.replace(".gltf", ".glb"))
scene = Scene.from_file(src)
scene.save(dst)
print(f"Packed {filename} -> {os.path.basename(dst)}")Exemple 3: Inspecció del gràfic de l’escena i informe d’exportació
Recorre el gràfic d’escena d’un fitxer COLLADA, recull estadístiques per malla i imprimeix un informe estructurat:
from aspose.threed import Scene
scene = Scene.from_file("assembly.dae")
report = []
def collect(node, path=""):
full_path = f"{path}/{node.name}" if node.name else path
if node.entity is not None:
mesh = node.entity
gt = node.global_transform
report.append({
"path": full_path,
"vertices": len(mesh.control_points),
"polygons": len(mesh.polygons),
"world_x": gt.translation.x,
"world_y": gt.translation.y,
"world_z": gt.translation.z,
})
for child in node.child_nodes:
collect(child, full_path)
collect(scene.root_node)
print(f"{'Path':<40} {'Verts':>6} {'Polys':>6} {'X':>8} {'Y':>8} {'Z':>8}")
print("-" * 78)
for entry in report:
print(
f"{entry['path']:<40} "
f"{entry['vertices']:>6} "
f"{entry['polygons']:>6} "
f"{entry['world_x']:>8.3f} "
f"{entry['world_y']:>8.3f} "
f"{entry['world_z']:>8.3f}"
)Consells i bones pràctiques
Selecció de format
- glTF 2.0 / GLB és el format d’intercanvi recomanat per a escenes que inclouen materials, animacions i jerarquies complexes. Prefereix GLB (binari) sobre glTF (text + fitxers externs) per a la portabilitat.
- STL és l’opció correcta quan el consumidor final és un tallador, una eina CAD o qualsevol eina que només necessiti geometria. STL no conté dades de material ni d’animació.
- OBJ té un ampli suport i és una bona elecció quan les dades de material s’han d’intercanviar amb eines antigues. Mantingues sempre el fitxer .mtl al costat del fitxer .obj.
Sistemes de coordenades
- Diferents aplicacions utilitzen diferents convencions d’orientació. Set
ObjLoadOptions.flip_coordinate_system = Truequan importeu fitxers OBJ des d’eines que utilitzen un sistema de coordenades right-handed si la vostra canalització espera coordenades left-handed, i a l’inrevés. - Verifiqueu la convenció d’eixos de l’actiu font abans d’aplicar cap gir. Girar dues vegades produeix una geometria incorrecta.
Normalització
- Establiu sempre
ObjLoadOptions.normalize_normal = Truequan la canalització downstream espera normals unitàries (per exemple, quan es passen normals a un shader o es fan dot-product lighting calculations). Les normals no normalitzades de fitxers OBJ mal formats provoquen artefactes d’il·luminació.
Rendiment
- Carregueu els fitxers una sola vegada i transformeu el gràfic de escena en memòria en lloc de tornar a carregar des del disc per a cada format de sortida. Un únic
Scene.from_file()crida seguida de múltiplesscene.save()crides són més eficients que càrregues repetides. - Quan processeu grans lots, construïu un únic
ObjLoadOptionsoStlSaveOptionsinstància i reutilitzeu-la a través de tots els fitxers en lloc de construir un nou objecte d’opcions per fitxer.
Gestió d’errors
- Envoluiu
scene.open()iscene.save()crides atry/exceptblocs quan es processen fitxers no fiables o subministrats per l’usuari. Informeu el nom del fitxer en els missatges d’excepció per simplificar la depuració en pipelines per lots.
Problemes comuns
| Problema | Causa | Resolució |
|---|---|---|
| La malla apareix reflectida després de carregar-la | Desajust de l’orientació del sistema de coordenades | Commuta ObjLoadOptions.flip_coordinate_system |
| Les normals tenen longitud zero | El fitxer font té normals no normalitzades | Estableix ObjLoadOptions.normalize_normal = True |
| Materials no carregats des d’OBJ | enable_materials és False (per defecte) | Estableix ObjLoadOptions.enable_materials = True |
| L’escena es carrega però tots els nodes són buits | El fitxer utilitza el format FBX | El parser FBX està en desenvolupament; utilitzeu OBJ, STL o glTF en el seu lloc |
| El model és extremadament petit o gran | El fitxer d’origen utilitza unitats no mètriques | Aplica ObjLoadOptions.scale per convertir a la teva unitat objectiu |
AttributeError a mesh.polygons | L’entitat Node no és una Mesh | Protegeix amb if node.entity is not None abans d’accedir a les propietats de l’entitat |
| El fitxer GLB és rebutjat pel visualitzador | Desat amb .gltf extensió | Utilitza .glb extensió en cridar scene.save() per activar el contenidor binari |
Preguntes freqüents
Quines versions de Python són compatibles? Les versions Python 3.7, 3.8, 3.9, 3.10, 3.11 i 3.12 són totes compatibles. La biblioteca és pur Python sense cap extensió nativa, de manera que funciona en qualsevol plataforma on s’executa CPython.
La biblioteca té alguna dependència externa? No. Aspose.3D FOSS per a Python només utilitza la biblioteca estàndard Python. S’instal·la com una única pip install aspose-3d-foss ordre sense passos addicionals.
Es suporta FBX? El tokenitzador FBX està implementat i pot analitzar el flux de tokens binari FBX, però el constructor de gràfic de escena que s’encarrega del tokenitzador té errors coneguts i no està llest per a producció. Utilitzeu OBJ, STL, glTF, COLLADA o 3MF per a un ús de producció fiable.
Puc utilitzar Aspose.3D FOSS en un producte comercial? Sí. La biblioteca es publica sota la llicència MIT, que permet l’ús en programari propietari i comercial sense pagaments de royalties, sempre que s’inclogui l’avís de llicència.
Com puc informar d’un error o sol·licitar un format? Obriu un issue al repositori. Incloeu un fitxer reproductor mínim i la versió de Python, el sistema operatiu i la versió de la biblioteca des de pip show aspose-3d-foss.
Resum de la referència de l’API
Classes principals
Scene: Contenidor de nivell superior per a una escena 3D. Punt d’entrada per aopen(),from_file(), isave().Node: Node d’arbre al gràfic de l’escena. Portaentity,transform,global_transform,material,child_nodes, iname.Entity: Classe base per a objectes adjunts a nodes (Mesh, Camera, Light).Transform: Posició, rotació (Quaternion) i escala en espai local per a un node.GlobalTransform: Transformació en espai mundial de només lectura calculada acumulant totes les transformacions dels avantpassats.
Geometria
Mesh: Malla de polígons ambcontrol_points(llista de vèrtexs) ipolygons.VertexElementNormal: Vectors normals per vèrtex o per polígon.VertexElementUV: Coordenades de textura UV per vèrtex.VertexElementVertexColor: Dades de color per vèrtex.VertexElementSmoothingGroup: Assignacions de grups d’allisat de polígons.
Materials
LambertMaterial: Model d’ombreig difús ambdiffuse_coloriemissive_color.PhongMaterial: Model d’ombreig especular que afegeixspecular_colorishininess.
Utilitats matemàtiques (aspose.threed.utilities)
Vector2: Vector 2D.Vector3: Vector 3D de doble precisió.Vector4: Vector 4D de doble precisió.FVector3: Vector 3D de precisió simple.Quaternion: Quaternió de rotació ambfrom_angle_axis(): ito_matrix().Matrix4: matriu de transformació 4×4.BoundingBox: Caixa delimitadora alineada ambminimum: imaximum: cantonades.
Animació
AnimationClip: Contenidor anomenat per a un conjunt de canals d’animació i els seus fotogrames clau.AnimationNode: Dades d’animació per node dins d’un clip.KeyFrame: Fotograma clau únic amb temps i valor.KeyframeSequence: Seqüència ordenada de fotogrames clau per a una única propietat animada.
Opcions de càrrega / desament
ObjLoadOptions: Configuració de càrrega específica d’OBJ:enable_materials,flip_coordinate_system,normalize_normal,scale.StlSaveOptions: Configuració d’exportació específica d’STL (mode binari vs. mode ASCII).
Càmeres i llums
Camera: Entitat de càmera amb configuració de projecció, adjuntable a unaNode.Light: Entitat de font de llum, adjuntable a unaNode.