Jak přeměnit 3D modely v Pythonu

Jak přeměnit 3D modely v Pythonu

Konverze formátu pomocí Aspose.3D FOSS pro Python je dvoustupňový proces: načtení do Scene Objekt, pak ukládat do požadovaného výstupního formátu. Protože všechna geometrie je držen v společném in-memory reprezentaci, žádné formát specifické mezichody jsou zapotřebí. V níže uvedených oddílech se zobrazují nejčastější konverze s pracovním kódem.

Krok za krokem

Krok 1: Nainstalujte balíček

asposefoss/3d is not yet published — build from source until it ships. See the project README for build instructions.

Nejsou požadovány žádné systémové knihovny, kompilátory ani další závislosti na běžném čase.


Krok 2: Nahrát zdrojový model

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

from aspose.threed import Scene

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

Pro soubory OBJ, kde potřebujete ovládat systém souřadnic nebo nakládání materiálu, 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 vedou k stejnému výsledku. Scene objekt pro následující krok uložení.


Krok 3: Zkontrolujte natáčené místo.

Před provedením konverze je třeba zkontrolovat, zda se geometrie načítá správně. chybí soubor, nepodporovaná funkce FBX nebo problém s traťovou stránkou. .mtl Všechny soubory mohou produkovat prázdnou 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žit do cílového formátu

Zavolej . scene.save() Přejít objekt speciální pro formát, který je určený k kontrole binárního výstupu ASCII, koordinačních osů a kompresi.

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

Uložení jako samostatný binární GLB místo .gltf + externí nárazníky, změnit výstup rozšíření na .glb:

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

OBJ až 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ý vzorec platí bez ohledu na zdrojový 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ýsledek

Po uložení potvrďte, že výstupní soubor existuje a má velikost jinou než nula. Pro podrobnější kontrolu ho znovu načtejte a porovnejte počet síťových sítí:

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

Obvyklé problémy a řešení

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

Zdrojový soubor může být naložen s nulovými mší. Přidejte krok inspekce z kroku 3 před ukládáním. Také potvrďte, že rozšíření souboru odpovídá skutečnému formátu; Aspose.3D používá rozšíření k výběru analyzátoru.

Výstup glTF chybí textury

3D FOSS přenáší geometrii a vlastnosti materiálu prostřednictvím konverze. .mtl, tyto soubory snímků nejsou automaticky kopírovány vedle .gltf.Po uložení kopírujte texturní snímky do výstupního adresáře ručně.

Výstup STL vypadá z vnitřku ven (obliční normály převráceny)

STL neobsahuje metadatové údaje o řádu zvlnění. Pokud jsou výstupní normály obráceny, nastavit StlSaveOptions možnost, pokud je k dispozici, nebo převrátit souřadnicový systém během zatížení: ObjLoadOptions.flip_coordinate_system = True.

ValueError: unsupported format při šetření

Zkontrolujte, zda je rozšíření výstupního souboru jedním z: .obj, .stl, .gltf, .glb, .dae, .3mf. Rozšíření jsou na Linuxu citlivé pro velké písmená.

Velmi velké soubory způsobují pomalé konverze

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


Časté otázky (FAQ)

Můžu převést soubor bez toho, abych ho napsala na disk?

Ano, obě. scene.open() a) scene.save() přijmout binární soubory podobné objekty kromě datových cest. Poslat jakýkoli objekt, který implementuje read() pro nakládku nebo write() pro uložení:

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)

Podporuje se FBX jako zdrojový formát pro konverzi?

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

Přežijí materiály přeměnu z OBJ na GLTF?

Základní vlastnosti materiálu Phong/Lambert (difusní barva) jsou přeneseny přes Scene Zbytek metodických parametrů nebo parametrů shaderu, které nelze vyjádřit v modelu materiálu glTF.

Můžu převést více souborů v smyčce?

Ano, každý. Scene.from_file() call vytváří 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á konverze hierarchii scény (roditelské/dítězové uzly)?

Ano. Strom uzlů je zachován tak daleko, jak to umožňuje cílový formát. Formáty jako STL ukládají pouze plochou geometrii bez struktury uzlu; hierarchie se na uložení rozlehlá. Formaty jako glTF a COLLADA uchovávají plnou hierarchii.

 Čeština