Caratteristiche e funzionalità

Caratteristiche e funzionalità

Aspose.3D FOSS per Python fornisce un’API completa di scene-graph per leggere, costruire e scrivere contenuti 3D in più formati standard del settore. Questa pagina documenta ogni area funzionale principale con esempi di codice Python funzionanti che utilizzano l’API reale della libreria.

Installazione e configurazione

Installa la libreria da PyPI con un unico comando:

pip install aspose-3d-foss

Non sono richiesti pacchetti di sistema aggiuntivi, estensioni native o toolchain del compilatore. La libreria è puramente Python e supporta Python 3.7 fino a 3.12 su Windows, macOS e Linux.

Per verificare l’installazione:

from aspose.threed import Scene

scene = Scene()
print("Aspose.3D FOSS installed successfully")
print(f"Root node name: {scene.root_node.name}")

Caratteristiche e funzionalità

Supporto dei formati

Aspose.3D FOSS per Python legge e scrive i seguenti formati:

FormatoEstensioneLetturaScritturaNote
Wavefront OBJ.obj.Caricamento materiale .mtl supportato
STL (binario).stlRoundtrip verificato (39 test)
STL (ASCII).stlRoundtrip verificato
glTF 2.0.gltfGrafo della scena completo preservato
GLB (binary glTF).glbContenitore binario a file singolo
COLLADA.daeGerarchia della scena e materiali
3MF.3mfFormato per la produzione additiva
FBX.fbxParzialeNoTokenizer funzionante; il parser ha bug noti

Caricamento OBJ con opzioni

ObjLoadOptions controlla come vengono analizzati i file 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")

Salvataggio in STL

StlSaveOptions controlla l’output binario vs. ASCII e altre impostazioni specifiche per 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)

Scene Graph

Tutti i contenuti 3D sono organizzati come un albero di Node oggetti. La radice dell’albero è scene.root_node. Ogni nodo può contenere nodi figli e trasportare un Entity (mesh, camera o light) più un Transform.

Attraversamento della gerarchia della scena

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)

Costruire una scena programmaticamente

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

Ispezionare GlobalTransform

GlobalTransform fornisce la trasformazione nello spazio mondiale di un nodo dopo aver accumulato tutte le trasformazioni dei suoi antenati:

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 Mesh

Il Mesh l’entità fornisce l’accesso ai dati geometrici includendo i punti di controllo (vertici), i poligoni e gli elementi dei vertici per normali, UV e colori.

Lettura della geometria 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)}")

Accesso agli elementi dei vertici

Gli elementi dei vertici contengono dati per vertice o per poligono. Gli elementi più comuni sono le normali, le coordinate UV, i colori dei vertici e i gruppi di smoothing:

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 dei materiali

Aspose.3D FOSS supporta due tipi di materiale: LambertMaterial (ombreggiatura diffusa) e PhongMaterial (ombreggiatura speculare). Entrambi vengono caricati automaticamente dai file .mtl quando si utilizza ObjLoadOptions con enable_materials = True.

Lettura dei materiali da 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}")

Assegnazione di un materiale tramite codice

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

Utility matematiche

Il aspose.threed.utilities module fornisce tutti i tipi matematici geometrici necessari per la costruzione e l’ispezione della scena.

ClasseScopo
Vector22D floating-point vector (UV coordinates)
Vector33D double-precision vector (positions, normals)
Vector44D double-precision vector (homogeneous coordinates)
FVector33D single-precision vector (compact storage)
QuaternionRappresentazione della rotazione senza gimbal lock
Matrix44×4 transformation matrix
BoundingBoxBounding box allineato agli assi con angoli min/max

Lavorare con le trasformazioni

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

Calcolo di un Bounding Box

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

Animazione

Aspose.3D FOSS fornisce un modello di animazione basato su AnimationClip, AnimationNode, KeyFrame, e KeyframeSequence. I dati di animazione memorizzati nei file caricati (glTF, COLLADA) sono accessibili tramite questi oggetti.

Lettura dei clip di animazione

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

Opzioni di caricamento e salvataggio

Ogni formato supportato ha una classe di opzioni corrispondente che controlla il comportamento di parsing e serializzazione.

ClasseFormatoProprietà chiave
ObjLoadOptionsOBJenable_materials, flip_coordinate_system, normalize_normal, scale
StlSaveOptionsSTLModalità di output binario vs. ASCII
(glTF usa i valori predefiniti)glTF / GLBGrafico della scena e materiali preservati automaticamente

Esempi di utilizzo

Esempio 1: Conversione da OBJ a STL

Converti un file OBJ (con i materiali) in STL binario, stampando le statistiche della mesh lungo il percorso:

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

Esempio 2: Impacchettamento batch da glTF a GLB

Risalva una directory di file glTF + texture separati come binari GLB autonomi:

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

Esempio 3: Ispezione del grafo della scena e rapporto di esportazione

Scorri il grafo della scena di un file COLLADA, raccogli le statistiche per mesh e stampa un rapporto strutturato:

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

Suggerimenti e migliori pratiche

Selezione del formato

  • glTF 2.0 / GLB è il formato di interscambio consigliato per scene che includono materiali, animazioni e gerarchie complesse. Preferire GLB (binario) rispetto a glTF (testo + file esterni) per la portabilità.
  • STL è la scelta giusta quando il consumatore a valle è un slicer, uno strumento CAD o qualsiasi tool che necessita solo della geometria. STL non contiene dati di materiale o animazione.
  • OBJ è ampiamente supportato ed è una buona scelta quando i dati dei materiali devono essere scambiati con strumenti più vecchi. Conserva sempre il file .mtl accanto al file .obj.

Sistemi di coordinate

  • Le diverse applicazioni usano convenzioni di mano diverse. Imposta ObjLoadOptions.flip_coordinate_system = True quando importi file OBJ da strumenti che usano un sistema di coordinate destro se il tuo flusso di lavoro si aspetta coordinate sinistre, e viceversa.
  • Verifica la convenzione degli assi dell’asset di origine prima di applicare qualsiasi ribaltamento. Ribaltare due volte produce geometria errata.

Normalizzazione

  • Imposta sempre ObjLoadOptions.normalize_normal = True quando il flusso di lavoro a valle si aspetta normali unitarie (ad esempio, quando si passano le normali a uno shader o si eseguono calcoli di illuminazione a prodotto scalare). Normali non normalizzate da file OBJ malformati causano artefatti di illuminazione.

Prestazioni

  • Carica i file una sola volta e trasforma il grafo della scena in memoria invece di ricaricare dal disco per ogni formato di output. Un singolo Scene.from_file() chiamata seguita da più scene.save() chiamate è più efficiente rispetto a caricamenti ripetuti.
  • Durante l’elaborazione di grandi lotti, costruisci un unico ObjLoadOptions o StlSaveOptions istanza e riutilizzala per tutti i file invece di creare un nuovo oggetto di opzioni per ogni file.

Gestione degli errori

  • Avvolgere scene.open() e scene.save() chiamate in try/except blocchi quando si elaborano file non attendibili o forniti dall’utente. Riporta il nome del file nei messaggi di eccezione per semplificare il debug nei pipeline batch.

Problemi comuni

ProblemaCauseRisoluzione
La mesh appare specchiata dopo il caricamentoDiscrepanza dell’orientamento del sistema di coordinateCommuta ObjLoadOptions.flip_coordinate_system
Le normali hanno lunghezza zeroIl file sorgente contiene normali non normalizzateImposta ObjLoadOptions.normalize_normal = True
Materiali non caricati dal file OBJenable_materials è False (predefinito)Imposta ObjLoadOptions.enable_materials = True
La scena si carica ma tutti i nodi sono vuotiIl file utilizza il formato FBXIl parser FBX è in sviluppo; usa OBJ, STL o glTF invece
Il modello è estremamente piccolo o grandeIl file di origine utilizza unità non metricheApplica ObjLoadOptions.scale per convertire nella tua unità di destinazione
AttributeError acceso mesh.polygonsL’entità nodo non è una MeshProteggi con if node.entity is not None prima di accedere alle proprietà dell’entità
Il file GLB è rifiutato dal visualizzatoreSalvato con .gltf estensioneUsa .glb estensione quando chiami scene.save() per attivare il contenitore binario

Domande frequenti

Quali versioni di Python sono supportate? Python 3.7, 3.8, 3.9, 3.10, 3.11 e 3.12 sono tutti supportati. La libreria è pure Python senza estensioni native, quindi funziona su qualsiasi piattaforma in cui gira CPython.

La libreria ha dipendenze esterne? No. Aspose.3D FOSS per Python utilizza solo la libreria standard Python. Si installa come un unico pip install aspose-3d-foss comando senza passaggi successivi.

Il formato FBX è supportato? Il tokenizer FBX è implementato e può analizzare il flusso di token binario FBX, ma il costruttore del grafo della scena sopra il tokenizer presenta bug noti e non è pronto per la produzione. Usa OBJ, STL, glTF, COLLADA o 3MF per un uso affidabile in produzione.

Posso usare Aspose.3D FOSS in un prodotto commerciale? Sì. La libreria è rilasciata sotto licenza MIT, che consente l’uso in software proprietario e commerciale senza pagamenti di royalty, a condizione che l’avviso di licenza sia incluso.

Come posso segnalare un bug o richiedere un formato? Apri un problema nel repository. Includi un file riproduttore minimo e la versione Python, il sistema operativo e la versione della libreria da pip show aspose-3d-foss.


Sommario del Riferimento API

Classi principali

  • Scene: Contenitore di livello superiore per una scena 3D. Punto di ingresso per open(), from_file(), e save().
  • Node: Nodo dell’albero nel grafo della scena. Trasporta entity, transform, global_transform, material, child_nodes, e name.
  • Entity: Classe base per gli oggetti collegati ai nodi (Mesh, Camera, Light).
  • Transform: Posizione, rotazione (Quaternion) e scala nello spazio locale per un nodo.
  • GlobalTransform: Trasformazione in spazio mondiale di sola lettura calcolata accumulando tutte le trasformazioni dei genitori.

Geometria

  • Mesh: Mesh poligonale con control_points (elenco dei vertici) e polygons.
  • VertexElementNormal: Vettori normali per vertice o per poligono.
  • VertexElementUV: Coordinate di texture UV per vertice.
  • VertexElementVertexColor: Dati di colore per vertice.
  • VertexElementSmoothingGroup: Assegnazioni dei gruppi di smussatura dei poligoni.

Materiali

  • LambertMaterial: Modello di shading diffuso con diffuse_color e emissive_color.
  • PhongMaterial: Aggiunta del modello di shading speculare specular_color : e shininess.

: Utility matematiche (aspose.threed.utilities)

  • Vector2: vettore 2D.
  • Vector3: vettore 3D a doppia precisione.
  • Vector4: vettore 4D a doppia precisione.
  • FVector3: vettore 3D a precisione singola.
  • Quaternion: quaternione di rotazione con from_angle_axis() e to_matrix().
  • Matrix4: matrice di trasformazione 4×4.
  • BoundingBox: bounding box allineato agli assi con minimum e maximum : vertici.

Animazione

  • AnimationClip: contenitore denominato per un insieme di canali di animazione e i loro fotogrammi chiave.
  • AnimationNode: dati di animazione per nodo all’interno di una clip.
  • KeyFrame: fotogramma chiave singolo con tempo e valore.
  • KeyframeSequence: sequenza ordinata di fotogrammi chiave per una singola proprietà animata.

Opzioni di caricamento / salvataggio

  • ObjLoadOptions: impostazioni di caricamento specifiche per OBJ: enable_materials, flip_coordinate_system, normalize_normal, scale.
  • StlSaveOptions: impostazioni di salvataggio specifiche per STL (modalità binaria vs. ASCII).

Telecamere e luci

  • Camera: entità fotocamera con impostazioni di proiezione, attaccabile a un Node.
  • Light: Entità sorgente luminosa, attaccabile a una Node.
 Italiano