Cara Memuat Model 3D di Python
Aspose.3D FOSS untuk Python menyediakan API yang sederhana untuk membuka file 3D tanpa ketergantungan native apa pun. Setelah memuat file ke dalam sebuah Scene objek, Anda dapat menelusuri hierarki node dan membaca data geometri mentah untuk setiap mesh dalam adegan.
Panduan Langkah-demi-Langkah
Langkah 1: Instal Paket
Instal Aspose.3D FOSS dari PyPI. Tidak diperlukan pustaka sistem tambahan.
pip install aspose-3d-fossVersi Python yang didukung: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.
Langkah 2: Impor Kelas Scene
The Scene kelas adalah wadah tingkat atas untuk semua data 3D. Impor kelas ini bersama dengan kelas opsi‑muat apa pun yang Anda perlukan.
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptionsSemua kelas publik berada di bawah aspose.threed atau sub‑paketnya (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).
Langkah 3: Muat File
Gunakan static Scene.from_file() metode untuk membuka format yang didukung apa pun. Perpustakaan mendeteksi format secara otomatis dari ekstensi file.
##Automatic format detection
scene = Scene.from_file("model.obj")Sebagai alternatif, buat sebuah Scene instansi dan panggil open(); berguna ketika Anda ingin mengirimkan opsi muat atau menangani kesalahan secara eksplisit:
scene = Scene()
scene.open("model.obj")Kedua metode mendukung file OBJ, STL (biner dan ASCII), glTF 2.0 / GLB, COLLADA (DAE), dan 3MF.
Langkah 4: Telusuri Node Scene
Sebuah adegan yang dimuat adalah pohon dari Node objek yang berakar di scene.root_node. Iterasi secara rekursif untuk menemukan semua node:
from aspose.threed import Scene, Node
scene = Scene.from_file("model.obj")
def walk(node: Node, depth: int = 0) -> None:
indent = " " * depth
print(f"{indent}Node: {node.name!r}")
for child in node.child_nodes:
walk(child, depth + 1)
walk(scene.root_node)Setiap Node dapat membawa nol atau lebih Entity objek (meshes, kamera, lampu). Periksa node.entities untuk melihat apa yang terpasang.
Langkah 5: Akses Data Vertex dan Poligon
Cast entitas node menjadi Mesh dan baca titik kontrolnya (posisi vertex) serta poligon (daftar indeks wajah):
from aspose.threed import Scene
from aspose.threed.entities import Mesh
scene = Scene.from_file("model.obj")
for node in scene.root_node.child_nodes:
for entity in node.entities:
if isinstance(entity, Mesh):
mesh: Mesh = entity
print(f"Mesh '{node.name}': "
f"{len(mesh.control_points)} vertices, "
f"{len(mesh.polygons)} polygons")
# First vertex position
if mesh.control_points:
v = mesh.control_points[0]
print(f" First vertex: ({v.x:.4f}, {v.y:.4f}, {v.z:.4f})")
# First polygon face (list of control-point indices)
if mesh.polygons:
print(f" First polygon: {mesh.polygons[0]}")mesh.control_points adalah daftar Vector4 objek; x, y, z menyimpan posisi dan w adalah koordinat homogen (biasanya 1.0).
mesh.polygons adalah daftar daftar bilangan bulat, di mana setiap daftar dalamnya adalah urutan indeks titik kontrol untuk satu wajah.
Langkah 6: Terapkan Opsi Pemuatan Spesifik Format
Untuk kontrol yang lebih halus atas cara file OBJ diinterpretasikan, berikan sebuah ObjLoadOptions instansi ke scene.open():
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions
options = ObjLoadOptions()
options.flip_coordinate_system = True # Convert right-hand Y-up to Z-up
options.scale = 0.01 # Convert centimetres to metres
options.enable_materials = True # Load .mtl material file
options.normalize_normal = True # Normalize all normals to unit length
scene = Scene()
scene.open("model.obj", options)Untuk file STL, kelas yang setara adalah StlLoadOptions. Untuk glTF, gunakan GltfLoadOptions. Lihat referensi API untuk daftar lengkap.
Masalah Umum dan Solusinya
FileNotFoundError saat memanggil Scene.from_file()
Path harus absolut atau relatif yang benar terhadap direktori kerja pada saat runtime. Gunakan pathlib.Path untuk membangun path yang dapat diandalkan:
from pathlib import Path
from aspose.threed import Scene
path = Path(__file__).parent / "assets" / "model.obj"
scene = Scene.from_file(str(path))mesh.polygons kosong setelah memuat file STL
File STL menyimpan segitiga sebagai faset mentah, bukan mesh terindeks. Setelah dimuat, poligon disintesis dari faset tersebut. Jika polygons terlihat kosong, periksa len(mesh.control_points); jika hitungannya merupakan kelipatan 3, geometri disimpan dalam bentuk tidak terindeks dan setiap tiga vertex berurutan membentuk satu segitiga.
Ketidaksesuaian sistem koordinat (model tampak diputar atau dicerminkan)
Berbagai alat menggunakan konvensi yang berbeda (Y-up vs Z-up, tangan kiri vs tangan kanan). Atur ObjLoadOptions.flip_coordinate_system = True atau terapkan rotasi pada root node Transform setelah memuat.
AttributeError: 'NoneType' object has no attribute 'polygons'
Daftar entitas sebuah node dapat berisi entitas non-mesh (kamera, lampu). Selalu lindungi dengan isinstance(entity, Mesh) sebelum melakukan casting.
Pertanyaan yang Sering Diajukan (FAQ)
Format 3D apa saja yang dapat saya muat?
OBJ (Wavefront), STL (biner dan ASCII), glTF 2.0 / GLB, COLLADA (DAE), dan 3MF. Tokenisasi file FBX didukung sebagian tetapi parsing lengkap belum selesai.
Apakah memuat file OBJ juga memuat .mtl material?
Ya, ketika ObjLoadOptions.enable_materials = True (default). Perpustakaan mencari .mtl file di direktori yang sama dengan .obj file. Jika .mtl hilang, geometri tetap dimuat dan peringatan dikeluarkan.
Bisakah saya memuat file dari aliran byte alih-alih path?
Ya. scene.open() menerima objek mirip file apa pun dengan .read() metode selain string jalur file. Berikan aliran biner terbuka (misalnya,., io.BytesIO) secara langsung. Scene.from_file() hanya menerima string jalur file.
Bagaimana cara mendapatkan normal permukaan?
Setelah memuat, periksa mesh.get_element(VertexElementType.NORMAL). Ini mengembalikan sebuah VertexElementNormal yang data daftar berisi satu vektor normal per referensi, dipetakan menurut mapping_mode dan reference_mode.
from aspose.threed.entities import Mesh, VertexElementType
normals = mesh.get_element(VertexElementType.NORMAL)
if normals:
print(normals.data[0]) # First normal vectorApakah perpustakaan thread-safe untuk memuat beberapa file secara bersamaan?
Setiap Scene objek bersifat independen. Memuat file terpisah ke dalam terpisah Scene instance dari thread terpisah aman selama Anda tidak membagikan satu Scene di antara thread tanpa penguncian eksternal.