Kako konvertovati 3D modele u Pythonu

Kako konvertovati 3D modele u Pythonu

Konverzija formata uz Aspose.3D FOSS za Python je dvostepeni proces: učitajte u Scene objekat, a zatim sačuvajte u željeni izlazni format. Pošto je sva geometrija zadržana u zajedničkoj internom predstavljanju, nisu potrebni format‑specifični međukoraci. Donji odeljci prikazuju najčešće konverzije sa radnim kodom.

Vodič korak po korak

Korak 1: Instalirajte paket

pip install aspose-3d-foss

Nisu potrebne sistemske biblioteke, kompajleri ili dodatne runtime zavisnosti.


Korak 2: Učitaj izvorni model

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

from aspose.threed import Scene

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

Za OBJ datoteke kod kojih je potrebno kontrolisati koordinatni sistem ili učitavanje materijala, koristite scene.open() sa 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 objekat za sledeći korak čuvanja.


Korak 3: Pregled učitane scene

Pre nego što se odlučite na konverziju, vredi proveriti da li je geometrija pravilno učitana. Nedostajući fajl, nepodržana FBX funkcija ili problem sa putanjom u .mtl fajlu mogu sve proizvesti 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: Sačuvajte u ciljani format

Pozovite scene.save() sa putanjom izlaza. Prosledite objekat save‑options specifičan za format za kontrolu binarnog naspram ASCII izlaza, koordinatnih osa i kompresije.

OBJ u STL (binarni)

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 sačuvali kao samostalni GLB binarni fajl umesto .gltf + eksternih bafera, promenite ekstenziju izlaza 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 važi bez obzira na izvorni format:

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: Proverite izlaz

Nakon čuvanja, potvrdite da izlazni fajl postoji i da ima nenultu veličinu. Za temeljitiju proveru, ponovo ga učitajte i uporedite 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 popravke

Izlazni fajl je kreiran, ali ne sadrži geometriju

Izvorni fajl može biti učitan bez ikakvih mreža. Dodajte korak inspekcije iz koraka 3 pre čuvanja. Takođe potvrdite da ekstenzija fajla 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 referiše spoljne slikovne fajlove u .mtl, ti slikovni fajlovi se ne kopiraju automatski uz .gltf. Kopirajte teksturne slike u izlazni direktorijum ručno nakon čuvanja.

STL izlaz izgleda unutra‑napolju (normale lica okrenute)

STL ne nosi metapodatke o redosledu obrtanja. Ako su izlazni normali invertovani, postavite opcije StlSaveOptions ako su dostupne, ili preokrenite koordinatni sistem prilikom učitavanja: ObjLoadOptions.flip_coordinate_system = True.

ValueError: unsupported format prilikom čuvanja

Proverite da je ekstenzija izlaznog fajla jedna od .obj, .stl, .gltf, .glb, .dae, .3mf. Ekstenzije su osetljive na veličinu slova na Linuxu.

Vrlo velike datoteke uzrokuju sporu konverziju

Aspose.3D FOSS obrađuje geometriju u memoriji. Za fajlove sa milionima poligona, obezbedite dovoljno RAM-a. Trenutno ne postoji API za streaming‑pisanje.


Često postavljana pitanja (FAQ)

Mogu li konvertovati fajl bez da ga prvo upišem na disk?

Да. И scene.open() и scene.save() прихватају бинарне објекте сличне датотеци, поред путања датотека. Проследите било који објекат који имплементира read() за учитавање или 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)

Da li je FBX podržan kao izvorni format za konverziju?

FBX tokenizacija je delimično implementirana, ali parser nije kompletan. FBX ulaz može proizvesti nepotpune scene. Koristite OBJ, STL, glTF, COLLADA ili 3MF kao pouzdane izvorne formate.

Da li će materijali preživeti konverziju iz OBJ u glTF?

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

Могу ли да конвертујем више датотека у петљи?

Да. Svaki Scene.from_file() poziv kreira nezavisni objekat, pa je petlja preko liste 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}")

Da li konverzija očuva hijerarhiju scene (roditeljski/dete čvorovi)?

Da. Stablo čvorova se čuva u meri u kojoj to dozvoljava odredišni format. Formati poput STL čuvaju samo ravnu geometriju bez strukture čvorova; hijerarhija se izravnava prilikom čuvanja. Formati poput glTF i COLLADA zadržavaju potpunu hijerarhiju.

 Српски