Característiques i funcionalitats

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-foss

No 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:

FormatExtensióLlegirEscriureNotes
Wavefront OBJ.obj.mtl suport de càrrega de material
STL (binari).stlRecórrer verificat (39 proves)
STL (ASCII).stlRecórrer verificat
glTF 2.0.gltfGraf de l’escena complet conservat
GLB (binary glTF).glbContenidor binari d’un sol fitxer
COLLADA.daeJerarquia d’escena i materials
3MF.3mfFormat de fabricació additiva
FBX.fbxParcialNoTokenitzador 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.

ClassePropòsit
Vector22D floating-point vector (UV coordinates)
Vector33D double-precision vector (positions, normals)
Vector44D double-precision vector (homogeneous coordinates)
FVector33D single-precision vector (compact storage)
QuaternionRepresentació de rotació sense bloqueig de gimbal
Matrix44×4 transformation matrix
BoundingBoxCaixa 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ó.

ClasseFormatPropietats clau
ObjLoadOptionsOBJenable_materials, flip_coordinate_system, normalize_normal, scale
StlSaveOptionsSTLMode de sortida binari vs. ASCII
(glTF utilitza valors per defecte)glTF / GLBEl 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 = True quan 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 = True quan 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últiples scene.save() crides són més eficients que càrregues repetides.
  • Quan processeu grans lots, construïu un únic ObjLoadOptions o StlSaveOptions instà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() i scene.save() crides a try/except blocs 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

ProblemaCausaResolució
La malla apareix reflectida després de carregar-laDesajust de l’orientació del sistema de coordenadesCommuta ObjLoadOptions.flip_coordinate_system
Les normals tenen longitud zeroEl fitxer font té normals no normalitzadesEstableix ObjLoadOptions.normalize_normal = True
Materials no carregats des d’OBJenable_materials és False (per defecte)Estableix ObjLoadOptions.enable_materials = True
L’escena es carrega però tots els nodes són buitsEl fitxer utilitza el format FBXEl parser FBX està en desenvolupament; utilitzeu OBJ, STL o glTF en el seu lloc
El model és extremadament petit o granEl fitxer d’origen utilitza unitats no mètriquesAplica ObjLoadOptions.scale per convertir a la teva unitat objectiu
AttributeError a mesh.polygonsL’entitat Node no és una MeshProtegeix amb if node.entity is not None abans d’accedir a les propietats de l’entitat
El fitxer GLB és rebutjat pel visualitzadorDesat 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 a open(), from_file(), i save().
  • Node: Node d’arbre al gràfic de l’escena. Porta entity, transform, global_transform, material, child_nodes, i name.
  • 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 amb control_points (llista de vèrtexs) i polygons.
  • 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 amb diffuse_color i emissive_color.
  • PhongMaterial: Model d’ombreig especular que afegeix specular_color i shininess.

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ó amb from_angle_axis() : i to_matrix().
  • Matrix4: matriu de transformació 4×4.
  • BoundingBox: Caixa delimitadora alineada amb minimum : i maximum : 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 una Node.
  • Light: Entitat de font de llum, adjuntable a una Node.
 Català