Cara Memuat Model 3D dalam Python
Aspose.3D FOSS untuk Python menyediakan API yang mudah untuk membuka fail 3D tanpa sebarang kebergantungan asli. Selepas memuatkan fail ke dalam a Scene objek, anda boleh menelusuri hierarki nod dan membaca data geometri mentah untuk setiap mesh dalam adegan.
Panduan Langkah demi Langkah
Langkah 1: Pasang Pakej
Pasang Aspose.3D FOSS dari PyPI. Tiada perpustakaan sistem tambahan diperlukan.
pip install aspose-3d-fossSahkan pemasangan:
import aspose.threed
print(aspose.threed.__version__) # e.g. 26.1.0Versi Python yang disokong: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.
Langkah 2: Import Kelas Scene
The Scene kelas adalah kontena peringkat atas untuk semua data 3D. Import ia bersama dengan mana-mana kelas pilihan-muat yang anda perlukan.
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptionsSemua kelas awam berada di bawah aspose.threed atau sub-pakejnya (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).
Langkah 3: Muat Fail
Gunakan statik Scene.from_file() kaedah untuk membuka sebarang format yang disokong. Perpustakaan mengesan format secara automatik daripada sambungan fail.
##Automatic format detection
scene = Scene.from_file("model.obj")Sebagai alternatif, buat satu Scene instans dan panggil open(); berguna apabila anda ingin menghantar pilihan muat atau mengendalikan ralat secara eksplisit:
scene = Scene()
scene.open("model.obj")Kedua-dua kaedah menyokong fail OBJ, STL (binari dan ASCII), glTF 2.0 / GLB, COLLADA (DAE), dan 3MF.
Langkah 4: Lintasi Nod Adegan
Sebuah adegan yang dimuatkan ialah pokok Node objek yang berakar pada scene.root_node. Ulang secara rekursif untuk mencari semua nod:
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 boleh membawa sifar atau lebih Entity objek (meshes, kamera, lampu). Periksa node.entities untuk melihat apa yang dilampirkan.
Langkah 5: Akses Data Vertex dan Poligon
Cast entiti nod kepada Mesh dan baca titik kawalannya (vertex positions) dan poligon (face index lists):
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 senarai Vector4 objek; x, y, z menyimpan kedudukan dan w adalah koordinat homogen (biasanya 1.0).
mesh.polygons adalah senarai senarai integer, di mana setiap senarai dalaman ialah set teratur indeks titik kawalan untuk satu muka.
Langkah 6: Terapkan Pilihan Muat Format-Specific
Untuk kawalan terperinci ke atas bagaimana fail OBJ ditafsirkan, hantarkan satu ObjLoadOptions instans kepada 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 fail STL, kelas setara ialah StlLoadOptions. Untuk glTF, gunakan GltfLoadOptions. Lihat Rujukan API untuk senarai penuh.
Isu Umum dan Penyelesaian
FileNotFoundError semasa memanggil Scene.from_file()
Laluan mesti mutlak atau relatif yang betul berbanding direktori kerja semasa runtime. Gunakan pathlib.Path untuk membina laluan yang boleh dipercayai:
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 selepas memuatkan fail STL
Fail STL menyimpan segitiga sebagai faset mentah, bukannya mesh berindeks. Selepas dimuatkan, poligon disintesis daripada faset-faset tersebut. Jika polygons kelihatan kosong, periksa len(mesh.control_points); jika kiraannya merupakan gandaan 3, geometri disimpan dalam bentuk tidak berindeks dan setiap tiga titik berturutan membentuk satu segitiga.
Ketidakpadanan sistem koordinat (model kelihatan diputar atau dipantulkan)
Alat yang berbeza menggunakan konvensi yang berbeza (Y-up vs Z-up, tangan kiri vs tangan kanan). Tetapkan ObjLoadOptions.flip_coordinate_system = True atau terapkan putaran pada nod akar Transform selepas memuatkan.
AttributeError: 'NoneType' object has no attribute 'polygons'
Senarai entiti nod mungkin mengandungi entiti bukan-mesh (kamera, lampu). Sentiasa lindungi dengan isinstance(entity, Mesh) sebelum menukar jenis.
Soalan Lazim (FAQ)
Format 3D mana yang boleh saya muatkan?
OBJ (Wavefront), STL (binari dan ASCII), glTF 2.0 / GLB, COLLADA (DAE), dan 3MF. Tokenisasi fail FBX disokong secara separa tetapi penguraian penuh belum selesai.
Adakah memuatkan fail OBJ juga memuatkan .mtl bahan?
Ya, apabila ObjLoadOptions.enable_materials = True (lalai). Perpustakaan mencari the .mtl fail dalam direktori yang sama dengan .obj fail. Jika .mtl tiada, geometri masih dimuatkan dan amaran dikeluarkan.
Bolehkah saya memuatkan fail daripada aliran bait dan bukannya laluan?
Scene.open() menerima rentetan laluan fail. Memuatkan dari aliran dalam memori tidak didedahkan dalam API semasa; tulis bait ke fail sementara terlebih dahulu.
Bagaimana saya dapat normal permukaan?
Selepas memuatkan, periksa mesh.get_element(VertexElementType.NORMAL). Ini mengembalikan satu VertexElementNormal yang data senarai mengandungi satu vektor normal bagi setiap rujukan, dipetakan mengikut 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 vectorAdakah perpustakaan thread-safe untuk memuatkan berbilang fail secara serentak?
Setiap Scene objek adalah bebas. Memuatkan fail berasingan ke dalam Scene instans daripada benang berasingan adalah selamat selagi anda tidak berkongsi satu Scene merentasi thread tanpa kunci luaran.