Kako pretvoriti 3D modele u Pythonu

Kako pretvoriti 3D modele u Pythonu

Konverzija formata s Aspose.3D FOSS za Python je dvofazni proces: učitajte u Scene objekt, a zatim spremite u željeni izlazni format. Budući da je sva geometrija pohranjena u zajedničkoj in-memory reprezentaciji, nisu potrebni format-specifični međukoraci. Donji odjeljci prikazuju najčešće konverzije s radnim kodom.

Vodič korak po korak

Korak 1: Instalirajte paket

pip install aspose-3d-foss

Nisu potrebne sistemske biblioteke, kompajleri ili dodatne runtime ovisnosti.


Korak 2: Učitaj izvorni model

Koristite Scene.from_file() za najjednostavniji slučaj: format se automatski otkriva iz ekstenzije datoteke:

from aspose.threed import Scene

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

Za OBJ datoteke u kojima trebate kontrolu nad koordinatnim sustavom ili učitavanjem materijala, koristite 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 pristupa proizvode identičan Scene objekt za sljedeći korak spremanja.


Korak 3: Pregled učitane scene

Prije nego što se odlučite za konverziju, vrijedno je provjeriti je li geometrija ispravno učitana. Nedostajuća datoteka, nepodržana FBX značajka ili problem s putanjom u .mtl datoteci mogu svi uzrokovati praznu scenu.

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

Korak 4: Spremi u odredišni format

Pozovite scene.save() s putanjom izlaza. Proslijedite objekt opcija spremanja specifičan za format za kontrolu binarnog vs ASCII izlaza, koordinatnih osi i kompresije.

OBJ u STL (binarno)

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

Da biste spremili kao samostalni GLB binarni format umjesto .gltf + vanjskih međuspremnika, promijenite izlazni nastavak u .glb:

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

OBJ u 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 u glTF 2.0

Isti obrazac primjenjuje se neovisno o izvornom formatu:

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

Korak 5: Provjeri izlaz

Nakon spremanja, provjerite postoji li izlazna datoteka i ima li nenultu veličinu. Za temeljitiju provjeru, učitajte je ponovno i usporedite broj mreža:

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

Uobičajeni problemi i rješenja

Izlazna datoteka je stvorena, ali ne sadrži geometriju

Izvorna datoteka možda je učitana s nula mreža. Dodajte korak inspekcije iz koraka 3 prije spremanja. Također provjerite da ekstenzija datoteke odgovara stvarnom formatu; Aspose.3D koristi ekstenziju za odabir parsera.

glTF izlaz nema teksture

Aspose.3D FOSS prenosi geometriju i svojstva materijala kroz konverziju. Ako izvorni OBJ referencira vanjske slikovne datoteke u .mtl, te slikovne datoteke se ne kopiraju automatski uz .gltf. Kopirajte teksturne slike u izlazni direktorij ručno nakon spremanja.

STL izlaz izgleda okrenut naopako (normale lica preokrenute)

STL ne nosi metapodatke o redoslijedu uvijanja. Ako su izlazni normali invertirani, postavite StlSaveOptions opcije ako su dostupne, ili preokrenite koordinatni sustav tijekom učitavanja: ObjLoadOptions.flip_coordinate_system = True.

ValueError: unsupported format pri spremanju

Provjerite je li ekstenzija izlazne datoteke jedna od .obj, .stl, .gltf, .glb, .dae, .3mf. Ekstenzije su osjetljive na veličinu slova na Linuxu.

Vrlo velike datoteke uzrokuju sporo pretvaranje

Aspose.3D FOSS obrađuje geometriju u memoriji. Za datoteke s milijunima poligona, osigurajte dovoljno RAM-a. Trenutno ne postoji API za streaming-pisanje.


Često postavljana pitanja (FAQ)

Mogu li pretvoriti datoteku bez da je najprije zapišem na disk?

Da. Oba scene.open() i scene.save() prihvaćaju binarne objekte slične datoteci, uz dodatak putanja do datoteka. Proslijedite bilo koji objekt koji implementira read() za učitavanje ili write() za spremanje:

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 li FBX podržan kao izvorni format za konverziju?

Tokenizacija FBX-a djelomično je implementirana, ali parser nije dovršen. FBX ulaz može proizvesti nepotpune scene. Koristite OBJ, STL, glTF, COLLADA ili 3MF kao pouzdane izvorne formate.

Hoće li materijali preživjeti konverziju iz OBJ u glTF?

Osnovna Phong/Lambert svojstva materijala (difuzna boja) prenose se kroz model Scene i zapisuju u glTF blok materijala. Proceduralni ili prilagođeni parametri sjenčivača koji se ne mogu izraziti u glTF modelu materijala se odbacuju.

Mogu li pretvoriti više datoteka u petlji?

Da. Svaki Scene.from_file() poziv stvara neovisni objekt, pa je petlja preko popisa putanja jednostavna:

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

Čuva li konverzija hijerarhiju scene (roditeljski/podređeni čvorovi)?

Da. Stablo čvorova se očuva koliko god to ciljani format dopušta. Formati poput STL pohranjuju samo ravnu geometriju bez strukture čvorova; hijerarhija se pri spremanju izravnava. Formati poput glTF i COLLADA zadržavaju potpunu hijerarhiju.

 Hrvatski