Jak převést 3D modely v Pythonu

Jak převést 3D modely v Pythonu

Formátová konverze s Aspose.3D FOSS pro Python je dvoustupňový proces: načíst do objektu Scene, poté uložit do požadovaného výstupního formátu. Protože veškerá geometrie je uložena ve společné paměťové reprezentaci, nejsou potřeba žádné formátově specifické mezikroky. Níže uvedené sekce ukazují nejčastější konverze s funkčním kódem.

Průvodce krok za krokem

Krok 1: Nainstalujte balíček

pip install aspose-3d-foss

Nejsou vyžadovány žádné systémové knihovny, kompilátory ani další běhové závislosti.


Krok 2: Načíst zdrojový model

Použijte Scene.from_file() pro nejjednodušší případ: formát je detekován automaticky z přípony souboru:

from aspose.threed import Scene

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

Pro soubory OBJ, kde potřebujete kontrolu nad souřadnicovým systémem nebo načítáním materiálů, použijte 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)

Oba přístupy vytvářejí identický objekt Scene pro následný krok uložení.


Krok 3: Prohlédněte načtenou scénu

Před provedením konverze stojí za to zkontrolovat, zda se geometrie načetla správně. Chybějící soubor, nepodporovaná funkce FBX nebo problém s cestou k souboru .mtl může vést k prázdné scéně.

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žit do cílového formátu

Zavolejte scene.save() s výstupní cestou. Předávejte objekt specifických možností uložení pro kontrolu binárního vs ASCII výstupu, souřadnicových os a komprese.

OBJ na STL (binární)

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

Chcete-li uložit jako samostatný binární GLB místo .gltf + externích bufferů, změňte výstupní pří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

Stejný vzor platí bez ohledu na vstupní formát:

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: Ověřte výstup

Po uložení potvrďte, že výstupní soubor existuje a má nenulovou velikost. Pro důkladnější kontrolu jej načtěte znovu a porovnejte počty meshů:

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

Běžné problémy a opravy

Výstupní soubor je vytvořen, ale neobsahuje žádnou geometrii

Zdrojový soubor se mohl načíst s nulovým počtem meshů. Přidejte krok kontroly ze kroku 3 před uložením. Také ověřte, že přípona souboru odpovídá skutečnému formátu; Aspose.3D používá příponu k výběru parseru.

glTF výstup postrádá textury

Aspose.3D FOSS přenáší geometrii a vlastnosti materiálu během konverze. Pokud zdrojový OBJ odkazuje na externí soubory obrázků v .mtl, tyto soubory obrázků nejsou automaticky zkopírovány spolu s .gltf. Zkopírujte textury do výstupního adresáře ručně po uložení.

STL výstup vypadá uvnitř ven (normály plochy jsou převráceny)

STL neobsahuje metadata o pořadí otáčení. Pokud jsou výstupní normály obráceny, nastavte možnosti StlSaveOptions, pokud jsou k dispozici, nebo při načítání převeďte souřadnicový systém: ObjLoadOptions.flip_coordinate_system = True.

ValueError: unsupported format při ukládání

Zkontrolujte, že přípona výstupního souboru je jedna z .obj, .stl, .gltf, .glb, .dae, .3mf. Přípony jsou v Linuxu rozlišovány podle velikosti písmen.

Velmi velké soubory způsobují pomalou konverzi

Aspose.3D FOSS zpracovává geometrii v paměti. Pro soubory s miliony polygonů zajistěte dostatečnou RAM. V současné době neexistuje API pro zápis streamování.


Často kladené otázky (FAQ)

Mohu převést soubor, aniž bych jej nejprve zapsal na disk?

Ano. Oba scene.open() i scene.save() přijímají binární objekty podobné souborům kromě cest k souborům. Předávejte libovolný objekt, který implementuje read() pro načítání nebo write() pro ukládání:

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 podporován jako vstupní formát pro konverzi?

Tokenizace FBX je částečně implementována, ale parser není kompletní. Vstup FBX může vytvářet neúplné scény. Použijte OBJ, STL, glTF, COLLADA nebo 3MF jako spolehlivé zdrojové formáty.

Přežijí materiály při konverzi OBJ na glTF?

Základní vlastnosti materiálu Phong/Lambert (difúzní barva) jsou přeneseny modelem Scene a zapsány do bloku materiálu glTF. Procedurální nebo vlastní parametry shaderu, které nelze vyjádřit v modelu materiálu glTF, jsou zahazovány.

Mohu převádět více souborů ve smyčce?

Ano. Každé volání Scene.from_file() vytvoří nezávislý objekt, takže smyčka přes seznam cest 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ává převod hierarchii scény (rodičovské/dětské uzly)?

Ano. Strom uzlů je zachován, pokud to cílový formát umožňuje. Formáty jako STL ukládají pouze plochou geometrii bez struktury uzlů; hierarchie je při ukládání zploštěna. Formáty jako glTF a COLLADA zachovávají plnou hierarchii.

 Čeština