Caracteristici și Funcționalități

Caracteristici și Funcționalități

Aspose.3D FOSS pentru Python oferă un API complet de graf de scenă pentru citirea, construirea și scrierea conținutului 3D în multiple formate standard din industrie. Această pagină documentează fiecare zonă majoră de funcționalitate cu exemple de cod Python funcționale care utilizează API-ul real al bibliotecii.

Instalare și configurare

Instalați biblioteca din PyPI cu o singură comandă:

pip install aspose-3d-foss

Nu sunt necesare pachete suplimentare de sistem, extensii native sau lanțuri de instrumente de compilare. Biblioteca este pur Python și suportă Python 3.7 până la 3.12 pe Windows, macOS și Linux.

Pentru a verifica instalarea:

from aspose.threed import Scene

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

Caracteristici și Funcționalități

Suport pentru formate

Aspose.3D FOSS pentru Python citește și scrie următoarele formate:

FormatExtensieCitireScriereNote
Wavefront OBJ.objDaDa.mtl încărcarea materialelor suportată
STL (binare).stlDaDaVerificare roundtrip (39 teste)
STL (ASCII).stlDaDaVerificare roundtrip
glTF 2.0.gltfDaDaGraficul complet al scenei păstrat
GLB (binary glTF).glbDaDaContainer binar cu un singur fișier
COLLADA.daeDaDaIerarhia scenei și materialele
3MF.3mfDaDaFormat de fabricație aditivă
FBX.fbxParțialNuTokenizatorul funcționează; parserul are buguri cunoscute

Încărcarea OBJ cu opțiuni

ObjLoadOptions controlează modul în care fișierele OBJ sunt analizate:

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

Salvarea în STL

StlSaveOptions controlează ieșirea binară vs. ASCII și alte setări specifice 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)

Graf de scenă

Tot conținutul 3D este organizat ca un arbore de Node obiecte. Rădăcina arborelui este scene.root_node. Fiecare nod poate conține noduri copil și poate purta un Entity (mesh, cameră sau lumină) plus un Transform.

Parcurgerea ierarhiei scenei

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)

Construirea unei scene programatic

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

Inspectarea GlobalTransform

GlobalTransform furnizează transformarea în spațiul lumii a unui nod după acumularea tuturor transformărilor strămoșilor:

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

The Mesh entitatea oferă acces la datele geometrice, inclusiv punctele de control (vârfuri), poligoanele și elementele de vârf pentru normale, UV-uri și culori.

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

Accesarea elementelor de vârf

Elementele de vârf conțin date per-vârf sau per-poligon. Cele mai comune elemente sunt normalele, coordonatele UV, culorile vârfului și grupurile de netezire:

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

Sistem de materiale

Aspose.3D FOSS suportă două tipuri de material: LambertMaterial (umbrire difuză) și PhongMaterial (specular shading). Ambele sunt încărcate automat din fișiere .mtl când se folosește ObjLoadOptions cu enable_materials = True.

Citirea materialelor din 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}")

Atribuirea unui material programatic

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

Utilitare matematice

The aspose.threed.utilities modulul furnizează toate tipurile de matematică geometrică necesare pentru construcția și inspecția scenei.

ClasăScop
Vector22D floating-point vector (UV coordinates)
Vector33D double-precision vector (positions, normals)
Vector44D double-precision vector (homogeneous coordinates)
FVector33D single-precision vector (compact storage)
QuaternionReprezentare a rotației fără blocaj de tip gimbal
Matrix44×4 transformation matrix
BoundingBoxCutie de delimitare aliniată pe axe cu colțuri min/max

Lucrul cu transformări

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

Calcularea unei cutii de delimitare

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

Animație

Aspose.3D FOSS furnizează un model de animație bazat pe AnimationClip, AnimationNode, KeyFrame, și KeyframeSequence. Datele de animație stocate în fișierele încărcate (glTF, COLLADA) sunt accesibile prin aceste obiecte.

Citirea clipurilor de animație

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

Opțiuni de încărcare și salvare

Fiecare format acceptat are o clasă de opțiuni corespunzătoare care controlează comportamentul de parsare și serializare.

ClasăFormatProprietăți cheie
ObjLoadOptionsOBJenable_materials, flip_coordinate_system, normalize_normal, scale
StlSaveOptionsSTLMod de ieșire binar vs. ASCII
(glTF folosește valorile implicite)glTF / GLBGraful scenei și materialele sunt păstrate automat

Exemple de utilizare

Exemplul 1: Conversia formatului OBJ în STL

Convertește un fișier OBJ (cu materiale) în STL binar, afișând statisticile rețelei pe parcurs:

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

Exemplul 2: Ambalare în lot a glTF în GLB

Re-salvează un director cu fișiere glTF + texturi separate ca binare GLB autonome:

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

Exemplul 3: Inspecția graficului de scenă și raportul de export

Parcurge graficul de scenă al unui fișier COLLADA, colectează statistici pe fiecare rețea și afișează un raport structurat:

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

Sfaturi și bune practici

Selectarea formatului

  • glTF 2.0 / GLB este formatul de interschimb recomandat pentru scene care includ materiale, animații și ierarhii complexe. Preferă GLB (binare) în loc de glTF (text + fișiere externe) pentru portabilitate.
  • STL este alegerea potrivită atunci când consumatorul din aval este un slicer, un instrument CAD sau orice alt instrument care are nevoie doar de geometrie. STL nu conține date de material sau animație.
  • OBJ este larg suportat și o alegere bună atunci când datele de material trebuie să fie schimbate cu instrumente mai vechi. Păstrează întotdeauna fișierul .mtl alături de fișierul .obj.

Sisteme de coordonate

  • Aplicațiile diferite folosesc convenții diferite de orientare a axelor. Set ObjLoadOptions.flip_coordinate_system = True când importați fișiere OBJ din instrumente care utilizează un sistem de coordonate drept, dacă pipeline‑ul dvs. așteaptă coordonate stânga, și invers.
  • Verificați convenția axelor activului sursă înainte de a aplica orice inversare. Inversarea de două ori produce geometrie incorectă.

Normalizare

  • Setați întotdeauna ObjLoadOptions.normalize_normal = True când pipeline‑ul din aval așteaptă normale unitare (de exemplu, când transmiteți normalele către un shader sau efectuați calcule de iluminare prin produs scalar). Normalele neunitare din fișiere OBJ prost formate cauzează artefacte de iluminare.

Performanță

  • Încărcați fișierele o singură dată și transformați graful de scenă în memorie în loc să le reîncărcați de pe disc pentru fiecare format de ieșire. Un singur Scene.from_file() apel urmat de multiple scene.save() apeluri este mai eficient decât încărcările repetate.
  • Când procesați loturi mari, construiți un singur ObjLoadOptions sau StlSaveOptions instanță și reutilizați‑o în toate fișierele în loc să construiți un nou obiect de opțiuni pentru fiecare fișier.

Gestionarea erorilor

  • Înfășurați scene.open() și scene.save() apeluri în try/except blocuri când se procesează fișiere neîncredere sau furnizate de utilizator. Raportați numele fișierului în mesajele de excepție pentru a simplifica depanarea în pipeline-uri batch.

Probleme comune

ProblemăCauzăRezolvare
Plasa apare oglindită după încărcareNeconcordanță a orientării sistemului de coordonateComută ObjLoadOptions.flip_coordinate_system
Normalele au lungime zeroFișierul sursă are normale ne-normalizateSetare ObjLoadOptions.normalize_normal = True
Materiale neîncărcate din OBJenable_materials este False (implicit)Setare ObjLoadOptions.enable_materials = True
Scena se încarcă, dar toate nodurile sunt goaleFișierul folosește formatul FBXParserul FBX este în dezvoltare; folosește în schimb OBJ, STL sau glTF
Modelul este extrem de mic sau mareFișierul sursă folosește unități non-metriceAplică ObjLoadOptions.scale pentru a converti la unitatea țintă
AttributeError pe mesh.polygonsEntitatea nod nu este un MeshProtecție cu if node.entity is not None înainte de a accesa proprietățile entității
Fișierul GLB este respins de vizualizatorSalvat cu .gltf extensieUtilizați .glb extensie când apelați scene.save() pentru a declanșa containerul binar

Întrebări frecvente

Ce versiuni Python sunt suportate? Python 3.7, 3.8, 3.9, 3.10, 3.11 și 3.12 sunt toate suportate. Biblioteca este pur Python fără nicio extensie nativă, așa că funcționează pe orice platformă pe care rulează CPython.

Are biblioteca dependențe externe? Nu. Aspose.3D FOSS pentru Python folosește doar biblioteca standard Python. Se instalează ca un singur pip install aspose-3d-foss comandă, fără pași suplimentari.

Este FBX suportat? Tokenizerul FBX este implementat și poate analiza fluxul binar de tokenuri FBX, dar constructorul de graf de scenă deasupra tokenizerului are buguri cunoscute și nu este pregătit pentru producție. Folosiți OBJ, STL, glTF, COLLADA sau 3MF pentru utilizare în producție fiabilă.

Pot folosi Aspose.3D FOSS într-un produs comercial? Da. Biblioteca este lansată sub licența MIT, care permite utilizarea în software proprietar și comercial fără plăți de redevențe, cu condiția să fie inclusă notificarea de licență.

Cum raportez un bug sau solicit un format? Deschideți o problemă în depozit. Includeți un fișier minimal de reproducere și versiunea Python, sistemul de operare și versiunea bibliotecii din pip show aspose-3d-foss.


Rezumat al referinței API

Clase de bază

  • Scene: Container de nivel superior pentru o scenă 3D. Punct de intrare pentru open(), from_file(),: , și save().
  • Node: Nod de arbore în graficul scenei. Poartă entity, transform, global_transform, material, child_nodes,: , și name.
  • Entity: Clasă de bază pentru obiectele atașate nodurilor (Mesh, Camera, Light).
  • Transform: Poziție, rotație (Quaternion) și scară în spațiul local pentru un nod.
  • GlobalTransform: Transformare în spațiul mondial doar în citire, calculată prin acumularea tuturor transformărilor strămoșilor.

Geometrie

  • Mesh: Plasă poligonală cu control_points : (listă de vârfuri) și polygons.
  • VertexElementNormal: Vectori normali per-vârf sau per-poligon.
  • VertexElementUV: Coordonate de textură UV per-vârf.
  • VertexElementVertexColor: Date de culoare per-vertex.
  • VertexElementSmoothingGroup: Atribuiri de grupuri de netezire a poligoanelor.

Materiale

  • LambertMaterial: Model de umbrire difuză cu diffuse_color : și emissive_color.
  • PhongMaterial: Model de umbrire speculară care adaugă specular_color : și shininess.

: Utilitare matematice (aspose.threed.utilities)

  • Vector2: Vector 2D.
  • Vector3: Vector 3D cu precizie dublă.
  • Vector4: Vector 4D cu precizie dublă.
  • FVector3: Vector 3D cu precizie simplă.
  • Quaternion: Quaternion de rotație cu from_angle_axis() : și to_matrix().
  • Matrix4: matrice de transformare 4×4.
  • BoundingBox: Cutie de delimitare aliniată pe axe cu minimum : și maximum : colțuri.

Animație

  • AnimationClip: Container denumit pentru un set de canale de animație și cadrele lor cheie.
  • AnimationNode: Date de animație pe nod în cadrul unui clip.
  • KeyFrame: Cadru cheie unic cu timp și valoare.
  • KeyframeSequence: Secvență ordonată de cadre cheie pentru o singură proprietate animată.

Opțiuni de încărcare / salvare

  • ObjLoadOptions: Setări de încărcare specifice OBJ: enable_materials, flip_coordinate_system, normalize_normal, scale.
  • StlSaveOptions: Setări de salvare specifice STL (mod binar vs. mod ASCII).

Camere și lumini

  • Camera: Entitate de cameră cu setări de proiecție, atașabilă la un Node.
  • Light: Entitate de sursă de lumină, atașabilă la un Node.
 Română