Cara Menukar Model 3D dalam Python

Cara Menukar Model 3D dalam Python

Penukaran format dengan Aspose.3D FOSS untuk Python adalah proses dua langkah: muat ke dalam objek Scene, kemudian simpan ke format output yang dikehendaki. Oleh kerana semua geometri disimpan dalam representasi memori bersama, tiada langkah perantaraan khusus format diperlukan. Bahagian di bawah menunjukkan penukaran paling umum dengan kod yang berfungsi.

Panduan Langkah demi Langkah

Langkah 1: Pasang Pakej

pip install aspose-3d-foss

Tiada perpustakaan sistem, penyusun, atau kebergantungan masa jalan tambahan diperlukan.


Langkah 2: Muat Model Sumber

Gunakan Scene.from_file() untuk kes paling mudah: format dikesan secara automatik daripada sambungan fail:

from aspose.threed import Scene

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

Untuk fail OBJ yang memerlukan kawalan ke atas sistem koordinat atau pemuatan bahan, gunakan scene.open() dengan 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)

Kedua-dua pendekatan menghasilkan objek Scene yang identik untuk langkah simpan seterusnya.


Langkah 3: Periksa Adegan yang Dimuat

Sebelum melakukan penukaran, adalah berbaloi untuk memeriksa bahawa geometri dimuatkan dengan betul. Fail yang hilang, ciri FBX yang tidak disokong, atau masalah laluan dengan fail .mtl semuanya boleh menghasilkan adegan kosong.

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

Langkah 4: Simpan ke Format Sasaran

Panggil scene.save() dengan laluan output. Hantar objek save-options khusus format untuk mengawal output binari vs ASCII, paksi koordinat, dan pemampatan.

OBJ ke STL (binari)

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

Untuk menyimpan sebagai binari GLB yang berdiri sendiri dan bukannya .gltf + penimbal luar, ubah sambungan output kepada .glb:

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

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

Corak yang sama terpakai tanpa mengira format sumber:

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

Langkah 5: Sahkan Output

Selepas menyimpan, sahkan fail output wujud dan mempunyai saiz bukan sifar. Untuk pemeriksaan yang lebih teliti, muat semula ia dan bandingkan kiraan 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")

Isu Umum dan Penyelesaian

Fail output dicipta tetapi tidak mengandungi geometri

Fail sumber mungkin telah dimuatkan dengan sifar mesh. Tambahkan langkah pemeriksaan dari Langkah 3 sebelum menyimpan. Juga sahkan bahawa sambungan fail sepadan dengan format sebenar; Aspose.3D menggunakan sambungan untuk memilih parser.

output glTF tiada tekstur

Aspose.3D FOSS membawa geometri dan sifat bahan melalui penukaran. Jika OBJ sumber merujuk fail imej luaran dalam .mtl, fail imej tersebut tidak disalin secara automatik bersama .gltf. Salin imej tekstur ke direktori output secara manual selepas menyimpan.

Output STL kelihatan terbalik (norma muka terbalik)

STL tidak membawa metadata susunan lilitan. Jika normal output terbalik, tetapkan pilihan StlSaveOptions jika tersedia, atau balikkan sistem koordinat semasa memuat: ObjLoadOptions.flip_coordinate_system = True.

ValueError: unsupported format semasa menyimpan

Semak sama ada sambungan fail output adalah salah satu daripada .obj, .stl, .gltf, .glb, .dae, .3mf. Sambungan adalah sensitif huruf pada Linux.

Berkas yang sangat besar menyebabkan penukaran perlahan

Aspose.3D FOSS memproses geometri dalam memori. Untuk fail dengan berjuta‑juta poligon, pastikan RAM yang mencukupi. Pada masa ini tiada API penulisan streaming.


Soalan Lazim (FAQ)

Bolehkah saya menukar fail tanpa menulisnya ke cakera terlebih dahulu?

Ya. Kedua scene.open() dan scene.save() menerima objek berjenis fail binari selain laluan fail. Hantar mana-mana objek yang melaksanakan read() untuk memuatkan atau write() untuk menyimpan:

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)

Adakah FBX disokong sebagai format sumber untuk penukaran?

Tokenisasi FBX telah dilaksanakan sebahagian, tetapi penghurai tidak lengkap. Input FBX mungkin menghasilkan adegan yang tidak lengkap. Gunakan OBJ, STL, glTF, COLLADA, atau 3MF sebagai format sumber yang boleh dipercayai.

Adakah bahan akan bertahan dalam penukaran OBJ-ke-glTF?

Ciri bahan Phong/Lambert asas (warna difus) dibawa melalui model Scene dan ditulis ke dalam blok bahan glTF. Parameter shader prosedural atau khusus yang tidak dapat diekspresikan dalam model bahan glTF dibuang.

Bolehkah saya menukar pelbagai fail dalam gelung?

Ya. Setiap panggilan Scene.from_file() menghasilkan objek yang bebas, jadi gelung atas senarai laluan adalah mudah:

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

Adakah penukaran mengekalkan hierarki adegan (nod induk/anak)?

Ya. Pokok nod dipelihara sejauh mana format sasaran membenarkannya. Format seperti STL hanya menyimpan geometri rata tanpa struktur nod; hierarki diratakan semasa menyimpan. Format seperti glTF dan COLLADA mengekalkan hierarki penuh.

 Bahasa Melayu