Fitur dan Fungsionalitas
Aspose.3D FOSS untuk Python menyediakan API scene-graph lengkap untuk membaca, membangun, dan menulis konten 3D dalam berbagai format standar industri. Halaman ini mendokumentasikan setiap area fitur utama dengan contoh kode Python yang berfungsi dan menggunakan API perpustakaan yang sebenarnya.
Instalasi dan Penyiapan
Instal perpustakaan dari PyPI dengan satu perintah:
pip install aspose-3d-fossTidak diperlukan paket sistem tambahan, ekstensi native, atau toolchain compiler. Perpustakaan ini murni Python dan mendukung Python 3.7 hingga 3.12 pada Windows, macOS, dan Linux.
Untuk memverifikasi instalasi:
from aspose.threed import Scene
scene = Scene()
print("Aspose.3D FOSS installed successfully")
print(f"Root node name: {scene.root_node.name}")Fitur dan Fungsionalitas
Dukungan Format
Aspose.3D FOSS untuk Python membaca dan menulis format berikut:
| Format | Ekstensi | Baca | Tulis | Catatan |
|---|---|---|---|---|
| Wavefront OBJ | .obj | Ya | Ya | .pemuatan material .mtl didukung |
| STL (biner) | .stl | Ya | Ya | Roundtrip terverifikasi (39 tes) |
| STL (ASCII) | .stl | Ya | Ya | Roundtrip terverifikasi |
| glTF 2.0 | .gltf | Ya | Ya | Grafik adegan lengkap dipertahankan |
| GLB (binary glTF) | .glb | Ya | Ya | Kontainer biner satu file |
| COLLADA | .dae | Ya | Ya | Hierarki adegan dan material |
| 3MF | .3mf | Ya | Ya | Format manufaktur aditif |
| FBX | .fbx | Sebagian | Tidak | Tokenizer berfungsi; parser memiliki bug yang diketahui |
Memuat OBJ dengan Opsi
ObjLoadOptions mengontrol cara file OBJ diparse:
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions
options = ObjLoadOptions()
options.enable_materials = True # Load accompanying .mtl file
options.flip_coordinate_system = False # Preserve original handedness
options.normalize_normal = True # Normalize vertex normals to unit length
options.scale = 1.0 # Apply a uniform scale factor at load time
scene = Scene()
scene.open("model.obj", options)
print(f"Loaded {len(scene.root_node.child_nodes)} top-level nodes")Menyimpan ke STL
StlSaveOptions mengontrol output biner vs. ASCII dan pengaturan khusus STL lainnya:
from aspose.threed import Scene
from aspose.threed.formats import StlSaveOptions
scene = Scene.from_file("model.obj")
options = StlSaveOptions()
scene.save("output.stl", options)Graf Adegan
Semua konten 3D diatur sebagai pohon dari Node objek. Akar dari pohon adalah scene.root_node. Setiap node dapat berisi node anak dan membawa sebuah Entity (mesh, kamera, atau cahaya) plus a Transform.
Menelusuri Hierarki Scene
from aspose.threed import Scene
scene = Scene.from_file("model.glb")
def traverse(node, depth=0):
indent = " " * depth
entity_type = type(node.entity).__name__ if node.entity else "none"
print(f"{indent}{node.name} [{entity_type}]")
for child in node.child_nodes:
traverse(child, depth + 1)
traverse(scene.root_node)Membangun Scene secara Programatik
from aspose.threed import Scene, Node, Entity
from aspose.threed.entities import Mesh
from aspose.threed.utilities import Vector3
scene = Scene()
root = scene.root_node
##Create a child node and position it
child = root.create_child_node("my_object")
child.transform.translation = Vector3(1.0, 0.0, 0.0)
child.transform.scaling = Vector3(2.0, 2.0, 2.0)
scene.save("constructed.glb")Memeriksa GlobalTransform
GlobalTransform memberikan transformasi ruang-dunia dari sebuah node setelah mengakumulasi semua transformasi nenek moyang:
from aspose.threed import Scene
scene = Scene.from_file("model.dae")
for node in scene.root_node.child_nodes:
gt = node.global_transform
print(f"Node: {node.name}")
print(f" World translation: {gt.translation}")
print(f" World scale: {gt.scale}")API Mesh
The Mesh entitas memberikan akses ke data geometri termasuk titik kontrol (vertices), poligon, dan elemen vertex untuk normal, UV, dan warna.
Membaca Geometri Mesh
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions
options = ObjLoadOptions()
options.enable_materials = True
options.flip_coordinate_system = False
scene = Scene()
scene.open("model.obj", options)
for node in scene.root_node.child_nodes:
if node.entity is None:
continue
mesh = node.entity
print(f"Mesh: {node.name}")
print(f" Vertices: {len(mesh.control_points)}")
print(f" Polygons: {len(mesh.polygons)}")Mengakses Elemen Vertex
Elemen vertex menyimpan data per-vertex atau per-poligon. Elemen yang paling umum adalah normal, koordinat UV, warna vertex, dan grup smoothing:
from aspose.threed import Scene
from aspose.threed.entities import VertexElementNormal, VertexElementUV
scene = Scene.from_file("model.obj")
for node in scene.root_node.child_nodes:
if node.entity is None:
continue
mesh = node.entity
# Iterate vertex elements to find normals and UVs
for element in mesh.vertex_elements:
if isinstance(element, VertexElementNormal):
print(f" Normals count: {len(element.data)}")
elif isinstance(element, VertexElementUV):
print(f" UV count: {len(element.data)}")Sistem Material
Aspose.3D FOSS mendukung dua tipe material: LambertMaterial (pencahayaan difus) dan PhongMaterial (pencahayaan spekular). Keduanya dimuat secara otomatis dari file .mtl saat menggunakan ObjLoadOptions dengan enable_materials = True.
Membaca Material dari OBJ
from aspose.threed import Scene
from aspose.threed.shading import LambertMaterial, PhongMaterial
from aspose.threed.formats import ObjLoadOptions
options = ObjLoadOptions()
options.enable_materials = True
scene = Scene()
scene.open("model.obj", options)
for node in scene.root_node.child_nodes:
mat = node.material
if mat is None:
continue
print(f"Node: {node.name}")
if isinstance(mat, PhongMaterial):
print(f" Type: Phong")
print(f" Diffuse: {mat.diffuse_color}")
print(f" Specular: {mat.specular_color}")
elif isinstance(mat, LambertMaterial):
print(f" Type: Lambert")
print(f" Diffuse: {mat.diffuse_color}")Menetapkan Material secara Programatik
from aspose.threed import Scene, Node
from aspose.threed.shading import PhongMaterial
from aspose.threed.utilities import Vector3
scene = Scene.from_file("model.glb")
material = PhongMaterial()
material.diffuse_color = Vector3(0.8, 0.2, 0.2) # Red diffuse
material.specular_color = Vector3(1.0, 1.0, 1.0) # White specular
##Apply to the first mesh node
for node in scene.root_node.child_nodes:
if node.entity is not None:
node.material = material
break
scene.save("recolored.glb")Utilitas Matematika
The aspose.threed.utilities modul menyediakan semua tipe matematika geometris yang diperlukan untuk konstruksi dan inspeksi adegan.
| Kelas | Tujuan |
|---|---|
Vector2 | 2D floating-point vector (UV coordinates) |
Vector3 | 3D double-precision vector (positions, normals) |
Vector4 | 4D double-precision vector (homogeneous coordinates) |
FVector3 | 3D single-precision vector (compact storage) |
Quaternion | Representasi rotasi tanpa gimbal lock |
Matrix4 | 4×4 transformation matrix |
BoundingBox | Bounding box yang sejajar sumbu dengan sudut min/maks |
Bekerja dengan Transformasi
from aspose.threed.utilities import Vector3, Quaternion, Matrix4
import math
##Build a rotation quaternion from axis-angle
axis = Vector3(0.0, 1.0, 0.0) # Y-axis
angle_rad = math.radians(45.0)
q = Quaternion.from_angle_axis(angle_rad, axis)
print(f"Quaternion: x={q.x:.4f} y={q.y:.4f} z={q.z:.4f} w={q.w:.4f}")
##Convert to rotation matrix
mat = q.to_matrix()
print(f"Rotation matrix row 0: {mat[0, 0]:.4f} {mat[0, 1]:.4f} {mat[0, 2]:.4f}")Menghitung Bounding Box
from aspose.threed import Scene
scene = Scene.from_file("model.stl")
# NOTE: mesh.get_bounding_box() is a stub — it always returns an empty BoundingBox()
# regardless of geometry. Compute bounds manually from control_points:
for node in scene.root_node.child_nodes:
if node.entity is None:
continue
mesh = node.entity
pts = mesh.control_points # returns a copy of the vertex list
if not pts:
continue
xs = [p.x for p in pts]
ys = [p.y for p in pts]
zs = [p.z for p in pts]
print(f"Mesh: {node.name}")
print(f" Min: ({min(xs):.3f}, {min(ys):.3f}, {min(zs):.3f})")
print(f" Max: ({max(xs):.3f}, {max(ys):.3f}, {max(zs):.3f})")Animasi
Aspose.3D FOSS menyediakan model animasi berbasis AnimationClip, AnimationNode, KeyFrame, dan KeyframeSequence. Data animasi yang disimpan dalam file yang dimuat (glTF, COLLADA) dapat diakses melalui objek-objek ini.
Membaca Klip Animasi
from aspose.threed import Scene
scene = Scene.from_file("animated.glb")
for clip in scene.animation_clips:
print(f"Clip: {clip.name} ({clip.start:.2f}s – {clip.stop:.2f}s)")
for anim_node in clip.animations:
print(f" Animation node: {anim_node.name}")
for sub in anim_node.sub_animations:
print(f" Sub-animation: {sub.name}")
for bp in anim_node.bind_points:
print(f" Bind point: {bp.name}")Opsi Muat dan Simpan
Setiap format yang didukung memiliki kelas opsi yang sesuai yang mengontrol perilaku parsing dan serialisasi.
| Kelas | Format | Properti Kunci |
|---|---|---|
ObjLoadOptions | OBJ | enable_materials, flip_coordinate_system, normalize_normal, scale |
StlSaveOptions | STL | Mode keluaran Biner vs. ASCII |
| (glTF menggunakan nilai default) | glTF / GLB | Grafik adegan dan material dipertahankan secara otomatis |
Contoh Penggunaan
Contoh 1: Konversi Format OBJ ke STL
Konversi file OBJ (dengan material) ke STL biner, sambil mencetak statistik mesh sepanjang proses:
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions
from aspose.threed.formats import StlSaveOptions
##Load OBJ with material support
load_opts = ObjLoadOptions()
load_opts.enable_materials = True
load_opts.flip_coordinate_system = False
load_opts.normalize_normal = True
scene = Scene()
scene.open("input.obj", load_opts)
##Report what was loaded
total_vertices = 0
total_polygons = 0
for node in scene.root_node.child_nodes:
if node.entity is not None:
mesh = node.entity
total_vertices += len(mesh.control_points)
total_polygons += len(mesh.polygons)
print(f" {node.name}: {len(mesh.control_points)} vertices, {len(mesh.polygons)} polygons")
print(f"Total: {total_vertices} vertices, {total_polygons} polygons")
##Save as STL
save_opts = StlSaveOptions()
scene.save("output.stl", save_opts)
print("Saved output.stl")Contoh 2: Pengemasan Batch glTF ke GLB
Simpan ulang sebuah direktori berisi file glTF + tekstur terpisah menjadi binary GLB yang berdiri sendiri:
import os
from aspose.threed import Scene
input_dir = "gltf_files"
output_dir = "glb_files"
os.makedirs(output_dir, exist_ok=True)
for filename in os.listdir(input_dir):
if not filename.endswith(".gltf"):
continue
src = os.path.join(input_dir, filename)
dst = os.path.join(output_dir, filename.replace(".gltf", ".glb"))
scene = Scene.from_file(src)
scene.save(dst)
print(f"Packed {filename} -> {os.path.basename(dst)}")Contoh 3: Inspeksi Grafik Adegan dan Laporan Ekspor
Jelajahi grafik adegan file COLLADA, kumpulkan statistik per-mesh, dan cetak laporan terstruktur:
from aspose.threed import Scene
scene = Scene.from_file("assembly.dae")
report = []
def collect(node, path=""):
full_path = f"{path}/{node.name}" if node.name else path
if node.entity is not None:
mesh = node.entity
gt = node.global_transform
report.append({
"path": full_path,
"vertices": len(mesh.control_points),
"polygons": len(mesh.polygons),
"world_x": gt.translation.x,
"world_y": gt.translation.y,
"world_z": gt.translation.z,
})
for child in node.child_nodes:
collect(child, full_path)
collect(scene.root_node)
print(f"{'Path':<40} {'Verts':>6} {'Polys':>6} {'X':>8} {'Y':>8} {'Z':>8}")
print("-" * 78)
for entry in report:
print(
f"{entry['path']:<40} "
f"{entry['vertices']:>6} "
f"{entry['polygons']:>6} "
f"{entry['world_x']:>8.3f} "
f"{entry['world_y']:>8.3f} "
f"{entry['world_z']:>8.3f}"
)Tips dan Praktik Terbaik
Pemilihan Format
- glTF 2.0 / GLB adalah format pertukaran yang direkomendasikan untuk adegan yang mencakup material, animasi, dan hierarki kompleks. Pilih GLB (biner) daripada glTF (teks + file eksternal) untuk portabilitas.
- STL adalah pilihan yang tepat ketika konsumen hilir adalah slicer, alat CAD, atau alat apa pun yang hanya membutuhkan geometri. STL tidak membawa data material atau animasi.
- OBJ didukung secara luas dan merupakan pilihan yang baik ketika data material harus dipertukarkan dengan alat lama. Selalu simpan file .mtl bersama file .obj.
Sistem Koordinat
- Berbagai aplikasi menggunakan konvensi handedness yang berbeda. Atur
ObjLoadOptions.flip_coordinate_system = Truesaat mengimpor file OBJ dari alat yang menggunakan sistem koordinat right-handed jika pipeline Anda mengharapkan koordinat left-handed, dan sebaliknya. - Verifikasi konvensi sumbu aset sumber sebelum menerapkan pembalikan apa pun. Membalik dua kali menghasilkan geometri yang tidak tepat.
Normalisasi
- Selalu atur
ObjLoadOptions.normalize_normal = Trueketika pipeline hilir mengharapkan normal satuan (misalnya, saat mengirim normal ke shader atau melakukan perhitungan pencahayaan dot-product). Normal yang tidak ternormalisasi dari file OBJ yang buruk dapat menyebabkan artefak pencahayaan.
Kinerja
- Muat file sekali dan transformasikan grafik adegan dalam memori daripada memuat ulang dari disk untuk setiap format output. Sebuah
Scene.from_file()panggilan diikuti oleh beberapascene.save()panggilan lebih efisien daripada pemuatan berulang. - Saat memproses batch besar, buat satu
ObjLoadOptionsatauStlSaveOptionsinstance dan gunakan kembali pada semua file alih-alih membuat objek opsi baru untuk setiap file.
Penanganan Kesalahan
- Bungkus
scene.open()danscene.save()panggilan dalamtry/exceptblok saat memproses file yang tidak tepercaya atau yang disediakan pengguna. Laporkan nama file dalam pesan pengecualian untuk mempermudah debugging dalam pipeline batch.
Masalah Umum
| Masalah | Penyebab | Solusi |
|---|---|---|
| Mesh muncul terbalik setelah dimuat | Ketidaksesuaian arah sistem koordinat | Alihkan ObjLoadOptions.flip_coordinate_system |
| Normal memiliki panjang nol | File sumber memiliki normal yang tidak ternormalisasi | Setel ObjLoadOptions.normalize_normal = True |
| Material tidak dimuat dari OBJ | enable_materials adalah False (default) | Setel ObjLoadOptions.enable_materials = True |
| Adegan dimuat tetapi semua node kosong | File menggunakan format FBX | Parser FBX sedang dalam pengembangan; gunakan OBJ, STL, atau glTF sebagai gantinya |
| Model sangat kecil atau sangat besar | File sumber menggunakan satuan non-metrik | Terapkan ObjLoadOptions.scale untuk mengonversi ke satuan target Anda |
AttributeError aktif mesh.polygons | Entitas node bukan Mesh | Lindungi dengan if node.entity is not None sebelum mengakses properti entitas |
| File GLB ditolak oleh penampil | Disimpan dengan .gltf ekstensi | Gunakan .glb ekstensi saat memanggil scene.save() untuk memicu kontainer biner |
Pertanyaan yang Sering Diajukan
Versi Python apa yang didukung? Python 3.7, 3.8, 3.9, 3.10, 3.11, dan 3.12 semuanya didukung. Perpustakaan ini murni Python tanpa ekstensi native, sehingga dapat berjalan di platform apa pun yang menjalankan CPython.
Apakah perpustakaan memiliki ketergantungan eksternal? Tidak. Aspose.3D FOSS untuk Python hanya menggunakan pustaka standar Python. Ia dipasang sebagai satu pip install aspose-3d-foss perintah tanpa langkah lanjutan.
Apakah FBX didukung? Tokenizer FBX telah diimplementasikan dan dapat mengurai aliran token FBX biner, tetapi pembangun scene-graph di atas tokenizer memiliki bug yang diketahui dan belum siap untuk produksi. Gunakan OBJ, STL, glTF, COLLADA, atau 3MF untuk penggunaan produksi yang dapat diandalkan.
Apakah saya dapat menggunakan Aspose.3D FOSS dalam produk komersial? Ya. Perpustakaan ini dirilis di bawah lisensi MIT, yang mengizinkan penggunaan dalam perangkat lunak proprietari dan komersial tanpa pembayaran royalti, asalkan pemberitahuan lisensi disertakan.
Bagaimana cara saya melaporkan bug atau meminta format? Buka sebuah isu di repositori. Sertakan file reproduksi minimal dan versi Python, sistem operasi, serta versi perpustakaan dari pip show aspose-3d-foss.
Ringkasan Referensi API
Kelas Inti
Scene: Kontainer tingkat atas untuk sebuah adegan 3D. Titik masuk untukopen(),from_file(), dansave().Node: Node pohon dalam grafik adegan. Membawaentity,transform,global_transform,material,child_nodes, danname.Entity: Kelas dasar untuk objek yang terpasang pada node (Mesh, Camera, Light).Transform: Posisi ruang-lokal, rotasi (Quaternion), dan skala untuk sebuah node.GlobalTransform: Transformasi ruang-dunia hanya-baca yang dihitung dengan mengakumulasi semua transformasi leluhur.
Geometri
Mesh: Mesh poligon dengancontrol_points(daftar vertex) danpolygons.VertexElementNormal: Vektor normal per-vertex atau per-poligon.VertexElementUV: Koordinat tekstur UV per-vertex.VertexElementVertexColor: Data warna per-vertex.VertexElementSmoothingGroup: Penugasan grup penghalusan poligon.
Material
LambertMaterial: Model shading difus dengandiffuse_colordanemissive_color.PhongMaterial: Menambahkan model shading spekularspecular_colordanshininess.
Utilitas Matematika (aspose.threed.utilities)
Vector2: vektor 2D.Vector3: vektor 3D double presisi.Vector4: vektor 4D double presisi.FVector3: vektor 3D presisi tunggal.Quaternion: Quaternion rotasi denganfrom_angle_axis(): danto_matrix().Matrix4: matriks transformasi 4×4.BoundingBox: Kotak pembatas yang sejajar sumbu denganminimum: danmaximum: sudut-sudut.
Animasi
AnimationClip: Kontainer bernama untuk sekumpulan saluran animasi dan keyframe-nya.AnimationNode: Data animasi per-node dalam sebuah klip.KeyFrame: Satu keyframe dengan waktu dan nilai.KeyframeSequence: Urutan terurut keyframe untuk satu properti yang dianimasikan.
Opsi Muat / Simpan
ObjLoadOptions: Pengaturan pemuatan khusus OBJ:enable_materials,flip_coordinate_system,normalize_normal,scale.StlSaveOptions: Pengaturan penyimpanan khusus STL (mode biner vs. ASCII).
Kamera dan Lampu
Camera: Entitas kamera dengan pengaturan proyeksi, dapat dilampirkan ke sebuahNode.Light: Entitas sumber cahaya, dapat dipasang keNode.