Hvordan konvertere 3D-modeller i Python

Hvordan konvertere 3D-modeller i Python

Formatkonvertering med Aspose.3D FOSS for Python er en totrinnsprosess: last inn i et Scene-objekt, og deretter lagre til ønsket outputformat. Siden all geometri holdes i en felles intern minne‑representasjon, er ingen formatspesifikke mellomtrinn nødvendige. Seksjonene nedenfor viser de mest vanlige konverteringene med fungerende kode.

Trinn-for-trinn guide

Steg 1: Installer pakken

pip install aspose-3d-foss

Ingen systembiblioteker, kompilatorer eller ekstra kjøretidsavhengigheter kreves.


Trinn 2: Last inn kilde-modellen

Bruk Scene.from_file() for det enkleste tilfellet: formatet oppdages automatisk fra filendelsen:

from aspose.threed import Scene

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

For OBJ‑filer der du trenger kontroll over koordinatsystemet eller materiallasting, bruk scene.open() med 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)

Begge tilnærmingene produserer et identisk Scene-objekt for det påfølgende lagringssteget.


Trinn 3: Inspiser den lastede scenen

Før du går videre med en konvertering, er det lurt å sjekke at geometrien ble lastet inn korrekt. En manglende fil, en ikke‑støttet FBX‑funksjon, eller et sti‑problem med en .mtl‑fil kan alle føre til en tom scene.

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

Steg 4: Lagre til målformatet

Kall scene.save() med utdata‑stien. Send inn et formatspesifikt lagringsalternativ‑objekt for kontroll over binær vs ASCII‑utdata, koordinatakser og komprimering.

OBJ til STL (binær)

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

For å lagre som en selvstendig GLB-binær i stedet for en .gltf + eksterne buffere, endre utdata‑utvidelsen til .glb:

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

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

Det samme mønsteret gjelder uavhengig av kildeformat:

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

Steg 5: Verifiser utdata

Etter lagring, bekreft at utdatafilen finnes og har en størrelse som er større enn null. For en mer grundig sjekk, last den inn på nytt og sammenlign antall 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")

Vanlige problemer og løsninger

Utdatafilen er opprettet, men inneholder ingen geometri

Kildefilen kan ha blitt lastet med null mesh‑er. Legg til inspeksjonstrinnet fra trinn 3 før lagring. Bekreft også at filendelsen samsvarer med det faktiske formatet; Aspose.3D bruker endelsen til å velge parseren.

glTF-utdata mangler teksturer

Aspose.3D FOSS overfører geometri‑ og materialegenskaper gjennom konvertering. Hvis kilde‑OBJ‑filen refererer til eksterne bildefiler i .mtl, blir ikke disse bildefilene automatisk kopiert sammen med .gltf. Kopier teksturbilder til mål‑mappen manuelt etter lagring.

STL-utdata ser innvendig ut (flippede flatenormaler)

STL inneholder ikke metadata om viklingsrekkefølge. Hvis de genererte normalene er invertert, sett StlSaveOptions‑alternativene hvis tilgjengelige, eller vend koordinatsystemet under lasting: ObjLoadOptions.flip_coordinate_system = True.

ValueError: unsupported format ved lagring

Kontroller at filutvidelsen for utdata er en av .obj, .stl, .gltf, .glb, .dae, .3mf. Utvidelser er case‑sensitiv på Linux.

Veldig store filer forårsaker treg konvertering

Aspose.3D FOSS behandler geometri i minnet. For filer med millioner av polygoner, sørg for tilstrekkelig RAM. Det finnes for øyeblikket ingen streaming-write API.


Ofte stilte spørsmål (FAQ)

Kan jeg konvertere en fil uten å skrive den til disk først?

Ja. Både scene.open() og scene.save() godtar binære fil‑lignende objekter i tillegg til filstier. Send inn ethvert objekt som implementerer read() for lasting eller write() for lagring:

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)

Er FBX støttet som kildeformat for konvertering?

FBX-tokenisering er delvis implementert, men parseren er ikke fullstendig. FBX-inndata kan gi ufullstendige scener. Bruk OBJ, STL, glTF, COLLADA eller 3MF som pålitelige kildeformater.

Vil materialer overleve en OBJ-til-glTF-konvertering?

Grunnleggende Phong/Lambert-materialegenskaper (diffus farge) blir overført gjennom Scene-modellen og skrevet inn i glTF-materialblokken. Prosedyre‑ eller egendefinerte shader‑parametere som ikke kan uttrykkes i glTF-materialmodellen, blir droppet.

Kan jeg konvertere flere filer i en løkke?

Ja. Hvert Scene.from_file()‑kall oppretter et uavhengig objekt, så en løkke over en liste med stier er enkelt:

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

Bevarer konverteringen scenehierarkiet (foreldre/barn-noder)?

Ja. Nodetreet bevares så langt målformatet tillater. Formater som STL lagrer kun flat geometri uten nodestruktur; hierarkiet blir flatt ved lagring. Formater som glTF og COLLADA beholder hele hierarkiet.

 Norsk