Comment convertir des modèles 3D en Python
La conversion de format avec Aspose.3D FOSS for Python est un processus en deux étapes : charger dans un objet Scene, puis enregistrer dans le format de sortie souhaité. Étant donné que toute la géométrie est conservée dans une représentation commune en mémoire, aucune étape intermédiaire spécifique à un format n’est nécessaire. Les sections ci‑dessous montrent les conversions les plus courantes avec du code fonctionnel.
Guide étape par étape
Étape 1 : Installer le package
pip install aspose-3d-fossAucune bibliothèque système, aucun compilateur ou dépendance d’exécution supplémentaire n’est requis.
Étape 2 : charger le modèle source
Utilisez Scene.from_file() pour le cas le plus simple: le format est détecté automatiquement à partir de l’extension du fichier:
from aspose.threed import Scene
scene = Scene.from_file("model.obj")Pour les fichiers OBJ où vous avez besoin de contrôler le système de coordonnées ou le chargement des matériaux, utilisez scene.open() avec ObjLoadOptions :
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions
options = ObjLoadOptions()
options.flip_coordinate_system = True # Convert to Z-up if needed
options.enable_materials = True # Load the accompanying .mtl file
options.normalize_normal = True
scene = Scene()
scene.open("model.obj", options)Les deux approches produisent un objet Scene identique pour l’étape d’enregistrement suivante.
Étape 3 : Inspecter la scène chargée
Avant de procéder à une conversion, il vaut la peine de vérifier que la géométrie a été chargée correctement. Un fichier manquant, une fonctionnalité FBX non prise en charge ou un problème de chemin avec un fichier .mtl peuvent tous produire une scène vide.
from aspose.threed import Scene
from aspose.threed.entities import Mesh
scene = Scene.from_file("model.obj")
mesh_count = 0
total_vertices = 0
def count_meshes(node) -> None:
global mesh_count, total_vertices
for entity in node.entities:
if isinstance(entity, Mesh):
mesh_count += 1
total_vertices += len(entity.control_points)
for child in node.child_nodes:
count_meshes(child)
count_meshes(scene.root_node)
print(f"Loaded {mesh_count} mesh(es), {total_vertices} total vertices")
if mesh_count == 0:
raise ValueError("Scene contains no geometry: check the source file path and format")Étape 4 : Enregistrer au format cible
Appelez scene.save() avec le chemin de sortie. Passez un objet d’options d’enregistrement spécifique au format pour contrôler la sortie binaire ou ASCII, les axes de coordonnées et la compression.
OBJ vers STL (binaire)
from aspose.threed import Scene
from aspose.threed.formats import StlSaveOptions
scene = Scene.from_file("model.obj")
save_opts = StlSaveOptions()
##StlSaveOptions defaults to binary output, which is more compact.
scene.save("model.stl", save_opts)
print("Saved model.stl")OBJ vers glTF 2.0
from aspose.threed import Scene
from aspose.threed.formats import GltfSaveOptions
scene = Scene.from_file("model.obj")
save_opts = GltfSaveOptions()
scene.save("model.gltf", save_opts)
print("Saved model.gltf")Pour enregistrer sous forme d’un binaire GLB autonome au lieu d’un .gltf + tampons externes, modifiez l’extension de sortie en .glb :
scene.save("model.glb", save_opts)OBJ vers 3MF
from aspose.threed import Scene
from aspose.threed.formats import ThreeMfSaveOptions
scene = Scene.from_file("model.obj")
save_opts = ThreeMfSaveOptions()
scene.save("model.3mf", save_opts)
print("Saved model.3mf")STL vers glTF 2.0
Le même modèle s’applique quel que soit le format source :
from aspose.threed import Scene
from aspose.threed.formats import GltfSaveOptions
scene = Scene.from_file("input.stl")
scene.save("output.gltf", GltfSaveOptions())
print("Saved output.gltf")Étape 5 : Vérifier la sortie
Après l’enregistrement, confirmez que le fichier de sortie existe et a une taille non nulle. Pour une vérification plus approfondie, rechargez‑le et comparez le nombre de maillages :
import os
from aspose.threed import Scene
from aspose.threed.entities import Mesh
output_path = "model.stl"
##Basic file-system check
size = os.path.getsize(output_path)
print(f"Output file size: {size} bytes")
if size == 0:
raise RuntimeError("Output file is empty: save may have failed silently")
##Round-trip verification: reload and count geometry
def _iter_nodes(node):
yield node
for child in node.child_nodes:
yield from _iter_nodes(child)
reloaded = Scene.from_file(output_path)
mesh_count = sum(
1
for node in _iter_nodes(reloaded.root_node)
for entity in node.entities
if isinstance(entity, Mesh)
)
print(f"Round-trip check: {mesh_count} mesh(es) in output")Problèmes courants et solutions
Fichier de sortie créé mais ne contient aucune géométrie
Le fichier source peut avoir été chargé avec zéro maillage. Ajoutez l’étape d’inspection de l’étape 3 avant d’enregistrer. Confirmez également que l’extension du fichier correspond au format réel ; Aspose.3D utilise l’extension pour sélectionner le parseur.
La sortie glTF ne contient pas les textures
Aspose.3D FOSS transporte les propriétés de géométrie et de matériau lors de la conversion. Si le fichier OBJ source référence des fichiers image externes dans le .mtl, ces fichiers image ne sont pas automatiquement copiés avec le .gltf. Copiez manuellement les images de texture dans le répertoire de sortie après l’enregistrement.
La sortie STL apparaît à l’envers (normales de face inversées)
STL ne contient pas de métadonnées d’ordre de winding. Si les normales de sortie sont inversées, définissez les options StlSaveOptions si elles sont disponibles, ou inversez le système de coordonnées lors du chargement : ObjLoadOptions.flip_coordinate_system = True.
ValueError: unsupported format lors de l’enregistrement
Vérifiez que l’extension du fichier de sortie est l’une de .obj, .stl, .gltf, .glb, .dae, .3mf. Les extensions sont sensibles à la casse sous Linux.
Très gros fichiers entraînent une conversion lente
Aspose.3D FOSS traite la géométrie en mémoire. Pour les fichiers contenant des millions de polygones, assurez-vous de disposer de suffisamment de RAM. Il n’existe actuellement aucune API d’écriture en streaming.
Foire aux questions (FAQ)
Puis-je convertir un fichier sans l’écrire d’abord sur le disque ?
Oui. Les deux scene.open() et scene.save() acceptent des objets binaires similaires à des fichiers en plus des chemins de fichiers. Passez tout objet qui implémente read() pour le chargement ou write() pour l’enregistrement :
import io
from aspose.threed import Scene
# Load from an in-memory buffer
data = open('model.obj', 'rb').read()
scene = Scene()
scene.open(io.BytesIO(data))
# Save to an in-memory buffer
buf = io.BytesIO()
scene.save(buf)Le FBX est‑il pris en charge comme format source pour la conversion ?
La tokenisation FBX est partiellement implémentée, mais l’analyseur n’est pas complet. L’entrée FBX peut produire des scènes incomplètes. Utilisez OBJ, STL, glTF, COLLADA ou 3MF comme formats source fiables.
Les matériaux survivront-ils à une conversion OBJ-vers-glTF ?
Les propriétés de matériau Phong/Lambert de base (couleur diffuse) sont transmises via le modèle Scene et écrites dans le bloc de matériau glTF. Les paramètres de shader procéduraux ou personnalisés non exprimables dans le modèle de matériau glTF sont ignorés.
Puis-je convertir plusieurs fichiers dans une boucle ?
Oui. Chaque appel Scene.from_file() crée un objet indépendant, donc une boucle sur une liste de chemins est simple :
from pathlib import Path
from aspose.threed import Scene
from aspose.threed.formats import StlSaveOptions
source_dir = Path("input")
output_dir = Path("output")
output_dir.mkdir(exist_ok=True)
opts = StlSaveOptions()
for obj_file in source_dir.glob("*.obj"):
scene = Scene.from_file(str(obj_file))
out_path = output_dir / obj_file.with_suffix(".stl").name
scene.save(str(out_path), opts)
print(f"Converted {obj_file.name} -> {out_path.name}")La conversion préserve-t-elle la hiérarchie de la scène (nœuds parent/enfant) ?
Oui. L’arborescence des nœuds est conservée dans la mesure où le format cible le permet. Les formats comme STL ne stockent que de la géométrie plate sans structure de nœuds ; la hiérarchie est aplatie lors de l’enregistrement. Les formats comme glTF et COLLADA conservent la hiérarchie complète.