Ako konvertovať 3D modely v Pythone

Ako konvertovať 3D modely v Pythone

Formátová konverzia s Aspose.3D FOSS pre Python je dvojkrokový proces: načítanie do objektu Scene, potom uloženie do požadovaného výstupného formátu. Keďže všetka geometria je uchovávaná v spoločnej pamäťovej reprezentácii, nie sú potrebné formátovo špecifické medzikroky. Nižšie uvedené sekcie ukazujú najbežnejšie konverzie s funkčným kódom.

Sprievodca krok za krokom

Krok 1: Nainštalujte balík

pip install aspose-3d-foss

Nie sú potrebné žiadne systémové knižnice, kompilátory ani ďalšie runtime závislosti.


Krok 2: Načítajte zdrojový model

Použite Scene.from_file() pre najjednoduchší prípad: formát sa deteguje automaticky z prípony súboru:

from aspose.threed import Scene

scene = Scene.from_file("model.obj")

Pre súbory OBJ, kde potrebujete kontrolu nad súradnicovým systémom alebo načítavaním materiálu, použite scene.open() s 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)

Obe prístupy vytvoria identický objekt Scene pre nasledujúci krok ukladania.


Krok 3: Skontrolujte načítanú scénu

Predtým, než sa pustíte do konverzie, stojí za to skontrolovať, či sa geometria načítala správne. Chýbajúci súbor, nepodporovaná funkcia FBX alebo problém s cestou k súboru .mtl môžu všetky spôsobiť prázdnu scénu.

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

Krok 4: Uložiť do cieľového formátu

Zavolajte scene.save() s výstupnou cestou. Odovzdajte objekt špecifických možností ukladania pre daný formát na kontrolu binárneho vs ASCII výstupu, súradnicových osí a kompresie.

OBJ do STL (binárny)

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

Ak chcete uložiť ako samostatný binárny GLB namiesto .gltf + externých bufferov, zmeňte výstupnú príponu na .glb:

scene.save("model.glb", save_opts)

OBJ do 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 na glTF 2.0

Rovnaký vzor platí bez ohľadu na formát zdroja:

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

Krok 5: Overte výstup

Po uložení potvrďte, že výstupný súbor existuje a má nenulovú veľkosť. Pre dôkladnejšiu kontrolu ho načítajte znova a porovnajte počty meshov:

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

Bežné problémy a riešenia

Výstupný súbor je vytvorený, ale neobsahuje žiadnu geometriu

Zdrojový súbor mohol byť načítaný s nulovým počtom meshov. Pridajte kontrolný krok z kroku 3 pred uložením. Tiež overte, že prípona súboru zodpovedá skutočnému formátu; Aspose.3D používa príponu na výber parsera.

V glTF výstupe chýbajú textúry

Aspose.3D FOSS prenáša geometriu a materiálové vlastnosti počas konverzie. Ak zdrojový OBJ odkazuje na externé súbory obrázkov v .mtl, tieto súbory obrázkov nie sú automaticky skopírované spolu s .gltf. Skopírujte textúrové obrázky do výstupného adresára manuálne po uložení.

STL výstup vyzerá dovnútra von (normály plôch prevrátené)

STL neobsahuje metadáta o poradí otáčania. Ak sú výstupné normály invertované, nastavte možnosti StlSaveOptions, ak sú k dispozícii, alebo preklopte súradnicový systém pri načítaní: ObjLoadOptions.flip_coordinate_system = True.

ValueError: unsupported format pri ukladaní

Skontrolujte, či je prípona výstupného súboru jedna z .obj, .stl, .gltf, .glb, .dae, .3mf. Prípony sú v Linuxe citlivé na veľkosť písmen.

Veľmi veľké súbory spôsobujú pomalú konverziu

Aspose.3D FOSS spracováva geometriu v pamäti. Pre súbory s miliónmi polygonov zabezpečte dostatočnú RAM. V súčasnosti neexistuje API na streamovací zápis.


Často kladené otázky (FAQ)

Môžem konvertovať súbor bez toho, aby som ho najprv zapísal na disk?

Áno. Oba scene.open() a scene.save() akceptujú binárne objekty podobné súborom okrem ciest k súborom. Pre načítanie odovzdajte akýkoľvek objekt, ktorý implementuje read(), alebo pre ukladanie write():

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)

Je FBX podporovaný ako zdrojový formát pre konverziu?

Tokenizácia FBX je čiastočne implementovaná, ale parser nie je kompletný. Vstup FBX môže vytvárať neúplné scény. Použite OBJ, STL, glTF, COLLADA alebo 3MF ako spoľahlivé zdrojové formáty.

Prežijú materiály konverziu OBJ‑na‑glTF?

Základné vlastnosti materiálu Phong/Lambert (difúzna farba) sú prenesené cez model Scene a zapísané do bloku materiálu glTF. Procedurálne alebo vlastné parametre shaderov, ktoré nie je možné vyjadriť v modeli materiálu glTF, sú zahodené.

Môžem konvertovať viacero súborov v slučke?

Áno. Každé volanie Scene.from_file() vytvára nezávislý objekt, takže slučka cez zoznam ciest je jednoduchá:

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

Zachová konverzia hierarchiu scény (rodič/dieťa uzly)?

Áno. Strom uzlov je zachovaný, pokiaľ to cieľový formát umožňuje. Formáty ako STL ukladajú iba plochú geometriu bez štruktúry uzlov; hierarchia sa pri ukladaní sploští. Formáty ako glTF a COLLADA zachovávajú úplnú hierarchiu.

 Slovenčina