Hur man konverterar 3D-modeller i Python
Formatkonvertering med Aspose.3D FOSS för Python är en tvåstegsprocess: ladda in i ett Scene‑objekt, sedan spara till önskat utdataformat. Eftersom all geometri hålls i en gemensam minnesrepresentation behövs inga format‑specifika mellansteg. Avsnitten nedan visar de vanligaste konverteringarna med fungerande kod.
Steg-för-steg-guide
Steg 1: Installera paketet
pip install aspose-3d-fossInga systembibliotek, kompilatorer eller ytterligare körningsberoenden krävs.
Steg 2: Ladda källmodellen
Använd Scene.from_file() för det enklaste fallet: formatet upptäcks automatiskt från filändelsen:
from aspose.threed import Scene
scene = Scene.from_file("model.obj")För OBJ-filer där du behöver kontroll över koordinatsystemet eller materialinläsning, använd 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)Båda tillvägagångssätten producerar ett identiskt Scene‑objekt för det efterföljande sparsteget.
Steg 3: Inspektera den laddade scenen
Innan du påbörjar en konvertering är det värt att kontrollera att geometrin har laddats korrekt. En saknad fil, en ej stödjande FBX-funktion eller ett sökvägsproblem med en .mtl-fil kan alla leda till en tom scen.
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: Spara till målformatet
Anropa scene.save() med utdata‑sökvägen. Skicka ett format‑specifikt sparalternativ‑objekt för att kontrollera binär‑ vs ASCII‑utdata, koordinataxlar och komprimering.
OBJ till 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 till 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")För att spara som en självständig GLB-binär istället för en .gltf + externa buffertar, ändra utdatafilens filändelse till .glb:
scene.save("model.glb", save_opts)OBJ till 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 till glTF 2.0
Samma mönster gäller oavsett källformat:
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: Verifiera utdata
Efter att du har sparat, bekräfta att utdatafilen finns och har en icke‑noll storlek. För en mer grundlig kontroll, ladda om den och jämför mesh‑antal:
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")Vanliga problem och lösningar
Utdatafilen skapas men innehåller ingen geometri
Källfilen kan ha laddats med noll meshar. Lägg till inspektionssteget från Steg 3 innan du sparar. Bekräfta också att filändelsen matchar det faktiska formatet; Aspose.3D använder ändelsen för att välja parsern.
glTF-utdata saknar texturer
Aspose.3D FOSS överför geometri‑ och materialegenskaper vid konvertering. Om käll‑OBJ refererar till externa bildfiler i .mtl, kopieras dessa bildfiler inte automatiskt tillsammans med .gltf. Kopiera texturbilder till utdata‑katalogen manuellt efter sparande.
STL-utdata ser inifrån och ut (ytnormaler omvända)
STL innehåller ingen metadata för varvningsordning. Om de utgående normalerna är omvända, ställ in StlSaveOptions‑alternativen om de finns tillgängliga, eller vänd koordinatsystemet vid inläsning: ObjLoadOptions.flip_coordinate_system = True.
ValueError: unsupported format vid sparande
Kontrollera att filändelsen för utdata är en av .obj, .stl, .gltf, .glb, .dae, .3mf. Filändelser är skiftlägeskänsliga på Linux.
Mycket stora filer orsakar långsam konvertering
Aspose.3D FOSS bearbetar geometri i minnet. För filer med miljontals polygoner, se till att ha tillräckligt med RAM. Det finns för närvarande inget streaming-write API.
Vanliga frågor (FAQ)
Kan jag konvertera en fil utan att skriva den till disk först?
Ja. Både scene.open() och scene.save() accepterar binära fil‑liknande objekt utöver filsökvägar. Skicka vilket objekt som helst som implementerar read() för inläsning eller write() för sparande:
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)Stöds FBX som källformat för konvertering?
FBX-tokenisering är delvis implementerad, men parsern är inte komplett. FBX-indata kan producera ofullständiga scener. Använd OBJ, STL, glTF, COLLADA eller 3MF som pålitliga källformat.
Kommer material överleva en OBJ-till-glTF-konvertering?
Grundläggande Phong/Lambert-materialegenskaper (diffus färg) förs vidare genom Scene-modellen och skrivs in i glTF-materialblocket. Procedurala eller anpassade shaderparametrar som inte kan uttryckas i glTF-materialmodellen släpps.
Kan jag konvertera flera filer i en loop?
Ja. Varje Scene.from_file()-anrop skapar ett oberoende objekt, så en loop över en lista med sökvägar är enkel:
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}")Bevarar konverteringen scenhierarkin (förälder/barn-noder)?
Ja. Nodträdet bevaras så långt målformatet tillåter. Format som STL lagrar endast platt geometri utan nodstruktur; hierarkin plattas ut vid sparning. Format som glTF och COLLADA behåller hela hierarkin.