Fonctionnalités et capacités

Fonctionnalités et capacités

Aspose.3D FOSS pour Python fournit une API complète de graphe de scène pour lire, construire et écrire du contenu 3D dans plusieurs formats standards de l’industrie. Cette page documente chaque domaine fonctionnel majeur avec des exemples de code Python fonctionnels qui utilisent l’API réelle de la bibliothèque.

Installation et configuration

Installez la bibliothèque depuis PyPI avec une seule commande :

pip install aspose-3d-foss

Aucun paquet système supplémentaire, aucune extension native, ni aucune chaîne d’outils de compilation ne sont requis. La bibliothèque est pure Python et prend en charge Python 3.7 à 3.12 sur Windows, macOS et Linux.

Pour vérifier l’installation :

from aspose.threed import Scene

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

Fonctionnalités et capacités

Prise en charge des formats

Aspose.3D FOSS pour Python lit et écrit les formats suivants :

FormatExtensionLireÉcrireRemarques
Wavefront OBJ.objOuiOui.Chargement du matériau .mtl pris en charge
STL (binaire).stlOuiOuiVérification du roundtrip (39 tests)
STL (ASCII).stlOuiOuiVérification du roundtrip
glTF 2.0.gltfOuiOuiGraph complet de la scène conservé
GLB (binary glTF).glbOuiOuiConteneur binaire à fichier unique
COLLADA.daeOuiOuiHiérarchie de scène et matériaux
3MF.3mfOuiOuiFormat de fabrication additive
FBX.fbxPartielNonLe tokenizer fonctionne ; le parser a des bugs connus

Chargement d’OBJ avec options

ObjLoadOptions contrôle la façon dont les fichiers OBJ sont analysés :

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

Enregistrement au format STL

StlSaveOptions contrôle la sortie binaire vs. ASCII et d’autres paramètres spécifiques à 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)

Graphe de scène

Tout le contenu 3D est organisé sous forme d’arbre de Node objets. La racine de l’arbre est scene.root_node. Chaque nœud peut contenir des nœuds enfants et porter un Entity (maillage, caméra ou lumière) plus un Transform.

Parcourir la hiérarchie de la scène

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)

Construire une scène par programmation

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

Inspecter GlobalTransform

GlobalTransform donne la transformation en espace mondial d’un nœud après avoir accumulé toutes les transformations des ancêtres :

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

Le Mesh l’entité donne accès aux données géométriques, y compris les points de contrôle (sommets), les polygones et les éléments de sommet pour les normales, les UV et les couleurs.

Lecture de la géométrie 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 aux éléments de sommet

Les éléments de sommet contiennent des données par sommet ou par polygone. Les éléments les plus courants sont les normales, les coordonnées UV, les couleurs de sommet et les groupes de lissage :

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

Système de matériaux

Aspose.3D FOSS prend en charge deux types de matériaux : LambertMaterial (ombrage diffus) et PhongMaterial (ombrage spéculaire). Les deux sont chargés automatiquement à partir des fichiers .mtl lors de l’utilisation ObjLoadOptions avec enable_materials = True.

Lecture des matériaux depuis 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}")

Assignation d’un matériau par programmation

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

Utilitaires mathématiques

Le aspose.threed.utilities module fournit tous les types mathématiques géométriques nécessaires à la construction et à l’inspection de scènes.

ClasseObjectif
Vector22D floating-point vector (UV coordinates)
Vector33D double-precision vector (positions, normals)
Vector44D double-precision vector (homogeneous coordinates)
FVector33D single-precision vector (compact storage)
QuaternionReprésentation de la rotation sans blocage de cardan
Matrix44×4 transformation matrix
BoundingBoxBoîte englobante alignée sur les axes avec coins min/max

Travailler avec les transformations

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

Calcul d’une boîte englobante

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

Animation

Aspose.3D FOSS fournit un modèle d’animation basé sur AnimationClip, AnimationNode, KeyFrame, et KeyframeSequence. Les données d’animation stockées dans les fichiers chargés (glTF, COLLADA) sont accessibles via ces objets.

Lecture des clips d’animation

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

Options de chargement et d’enregistrement

Chaque format pris en charge possède une classe d’options correspondante qui contrôle le comportement d’analyse et de sérialisation.

ClasseFormatPropriétés clés
ObjLoadOptionsOBJenable_materials, flip_coordinate_system, normalize_normal, scale
StlSaveOptionsSTLMode de sortie binaire vs. ASCII
(glTF utilise les valeurs par défaut)glTF / GLBGraph de scène et matériaux préservés automatiquement

Exemples d’utilisation

Exemple 1 : Conversion du format OBJ vers STL

Convertir un fichier OBJ (avec matériaux) en STL binaire, en affichant les statistiques du maillage au fur et à mesure :

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 : Empaquetage par lots de glTF vers GLB

Réenregistrer un répertoire contenant des fichiers glTF + textures séparés en binaires GLB autonomes :

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 : Inspection du graphe de scène et rapport d’exportation

Parcourir le graphe de scène d’un fichier COLLADA, collecter les statistiques par maillage et imprimer un rapport structuré :

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

Conseils et bonnes pratiques

Sélection du format

  • glTF 2.0 / GLB est le format d’échange recommandé pour les scènes incluant des matériaux, des animations et des hiérarchies complexes. Privilégiez GLB (binaire) plutôt que glTF (texte + fichiers externes) pour la portabilité.
  • STL est le bon choix lorsque le consommateur en aval est un trancheur, un outil CAO ou tout autre outil qui ne nécessite que la géométrie. STL ne contient aucune donnée de matériau ou d’animation.
  • OBJ est largement supporté et constitue un bon choix lorsque les données de matériau doivent être échangées avec des outils plus anciens. Conservez toujours le fichier .mtl à côté du fichier .obj.

Systèmes de coordonnées

  • Différentes applications utilisent des conventions d’orientation différentes. Set ObjLoadOptions.flip_coordinate_system = True lors de l’importation de fichiers OBJ provenant d’outils qui utilisent un système de coordonnées right‑handed si votre pipeline attend des coordonnées left‑handed, et vice‑versa.
  • Vérifiez la convention d’axes de l’actif source avant d’appliquer tout retournement. Un retournement double produit une géométrie incorrecte.

Normalisation

  • Toujours définir ObjLoadOptions.normalize_normal = True lorsque le pipeline en aval attend des normales unitaires (par exemple, lors du passage des normales à un shader ou du calcul d’éclairage par produit scalaire). Les normales non normalisées provenant de fichiers OBJ mal formés provoquent des artefacts d’éclairage.

Performance

  • Chargez les fichiers une fois et transformez le graphe de scène en mémoire plutôt que de recharger depuis le disque pour chaque format de sortie. Un seul Scene.from_file() appel suivi de plusieurs scene.save() appels est plus efficace que des chargements répétés.
  • Lors du traitement de gros lots, construisez un seul ObjLoadOptions ou StlSaveOptions instance et réutilisez‑la pour tous les fichiers au lieu de créer un nouvel objet d’options par fichier.

Gestion des erreurs

  • Enveloppez scene.open() et scene.save() appels dans try/except blocs lors du traitement de fichiers non fiables ou fournis par l’utilisateur. Signalez le nom de fichier dans les messages d’exception pour simplifier le débogage dans les pipelines batch.

Problèmes courants

ProblèmeCauseSolution
Le maillage apparaît en miroir après le chargementIncohérence de la main du système de coordonnéesBasculer ObjLoadOptions.flip_coordinate_system
Les normales ont une longueur nulleLe fichier source contient des normales non normaliséesDéfinir ObjLoadOptions.normalize_normal = True
Matériaux non chargés depuis OBJenable_materials est False (par défaut)Définir ObjLoadOptions.enable_materials = True
La scène se charge mais tous les nœuds sont videsLe fichier utilise le format FBXLe parseur FBX est en cours de développement ; utilisez OBJ, STL ou glTF à la place
Le modèle est très petit ou très grandLe fichier source utilise des unités non métriquesAppliquer ObjLoadOptions.scale pour convertir en votre unité cible
AttributeError sur mesh.polygonsL’entité Node n’est pas un MeshProtéger avec if node.entity is not None avant d’accéder aux propriétés de l’entité
Le fichier GLB est rejeté par le visualiseurEnregistré avec .gltf extensionUtilisez .glb l’extension lors de l’appel scene.save() pour déclencher le conteneur binaire

Foire aux questions

Quelles versions de Python sont prises en charge ? Les versions Python 3.7, 3.8, 3.9, 3.10, 3.11 et 3.12 sont toutes prises en charge. La bibliothèque est pure Python sans extension native, elle fonctionne donc sur toute plateforme où CPython s’exécute.

La bibliothèque a-t-elle des dépendances externes ? Non. Aspose.3D FOSS pour Python n’utilise que la bibliothèque standard Python. Il s’installe en une seule pip install aspose-3d-foss commande sans étapes supplémentaires.

FBX est-il pris en charge ? Le tokenizer FBX est implémenté et peut analyser le flux binaire de tokens FBX, mais le constructeur de graphe de scène au-dessus du tokenizer présente des bugs connus et n’est pas prêt pour la production. Utilisez OBJ, STL, glTF, COLLADA ou 3MF pour un usage fiable en production.

Puis-je utiliser Aspose.3D FOSS dans un produit commercial ? Oui. La bibliothèque est publiée sous licence MIT, qui autorise l’utilisation dans des logiciels propriétaires et commerciaux sans paiement de redevances, à condition que l’avis de licence soit inclus.

Comment signaler un bug ou demander un format ? Ouvrez une issue dans le dépôt. Incluez un fichier de reproduction minimal ainsi que la version Python, le système d’exploitation et la version de la bibliothèque provenant de pip show aspose-3d-foss.


Résumé de la référence API

Classes de base

  • Scene: Conteneur de niveau supérieur pour une scène 3D. Point d’entrée pour open(), from_file(),: , et save().
  • Node: Nœud d’arbre dans le graphe de scène. Contient entity, transform, global_transform, material, child_nodes,: , et name.
  • Entity: Classe de base pour les objets attachés aux nœuds (Mesh, Camera, Light).
  • Transform: Position, rotation (Quaternion) et échelle en espace local pour un nœud.
  • GlobalTransform: Transformation en espace mondial en lecture seule calculée en accumulant toutes les transformations des ancêtres.

Géométrie

  • Mesh: Maillage polygonal avec control_points : (liste de sommets) et polygons.
  • VertexElementNormal: Vecteurs normaux par sommet ou par polygone.
  • VertexElementUV: Coordonnées de texture UV par sommet.
  • VertexElementVertexColor: Données de couleur par sommet.
  • VertexElementSmoothingGroup: Affectations de groupes de lissage de polygones.

Matériaux

  • LambertMaterial: Modèle d’ombrage diffus avec diffuse_color : et emissive_color.
  • PhongMaterial: Modèle d’ombrage spéculaire ajoutant specular_color : et shininess.

: Utilitaires mathématiques (aspose.threed.utilities)

  • Vector2: Vecteur 2D.
  • Vector3: Vecteur 3D double précision.
  • Vector4: Vecteur 4D double précision.
  • FVector3: Vecteur 3D simple précision.
  • Quaternion: Quaternion de rotation avec from_angle_axis() : et to_matrix().
  • Matrix4: matrice de transformation 4×4.
  • BoundingBox: Boîte englobante alignée sur les axes avec minimum : et maximum : coins.

Animation

  • AnimationClip: Conteneur nommé pour un ensemble de canaux d’animation et leurs images clés.
  • AnimationNode: Données d’animation par nœud dans un clip.
  • KeyFrame: Image clé unique avec le temps et la valeur.
  • KeyframeSequence: Séquence ordonnée d’images clés pour une seule propriété animée.

Options de chargement / d’enregistrement

  • ObjLoadOptions: Paramètres de chargement spécifiques à OBJ: enable_materials, flip_coordinate_system, normalize_normal, scale.
  • StlSaveOptions: Paramètres d’enregistrement spécifiques à STL (mode binaire vs. mode ASCII).

Caméras et lumières

  • Camera: Entité caméra avec paramètres de projection, attachable à un Node.
  • Light: Entité source de lumière, attachable à un Node.
 Français