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-foss

Tidak 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:

FormatEkstensiBacaTulisCatatan
Wavefront OBJ.objYaYa.pemuatan material .mtl didukung
STL (biner).stlYaYaRoundtrip terverifikasi (39 tes)
STL (ASCII).stlYaYaRoundtrip terverifikasi
glTF 2.0.gltfYaYaGrafik adegan lengkap dipertahankan
GLB (binary glTF).glbYaYaKontainer biner satu file
COLLADA.daeYaYaHierarki adegan dan material
3MF.3mfYaYaFormat manufaktur aditif
FBX.fbxSebagianTidakTokenizer 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.

KelasTujuan
Vector22D floating-point vector (UV coordinates)
Vector33D double-precision vector (positions, normals)
Vector44D double-precision vector (homogeneous coordinates)
FVector33D single-precision vector (compact storage)
QuaternionRepresentasi rotasi tanpa gimbal lock
Matrix44×4 transformation matrix
BoundingBoxBounding 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.

KelasFormatProperti Kunci
ObjLoadOptionsOBJenable_materials, flip_coordinate_system, normalize_normal, scale
StlSaveOptionsSTLMode keluaran Biner vs. ASCII
(glTF menggunakan nilai default)glTF / GLBGrafik 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 = True saat 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 = True ketika 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 beberapa scene.save() panggilan lebih efisien daripada pemuatan berulang.
  • Saat memproses batch besar, buat satu ObjLoadOptions atau StlSaveOptions instance dan gunakan kembali pada semua file alih-alih membuat objek opsi baru untuk setiap file.

Penanganan Kesalahan

  • Bungkus scene.open() dan scene.save() panggilan dalam try/except blok saat memproses file yang tidak tepercaya atau yang disediakan pengguna. Laporkan nama file dalam pesan pengecualian untuk mempermudah debugging dalam pipeline batch.

Masalah Umum

MasalahPenyebabSolusi
Mesh muncul terbalik setelah dimuatKetidaksesuaian arah sistem koordinatAlihkan ObjLoadOptions.flip_coordinate_system
Normal memiliki panjang nolFile sumber memiliki normal yang tidak ternormalisasiSetel ObjLoadOptions.normalize_normal = True
Material tidak dimuat dari OBJenable_materials adalah False (default)Setel ObjLoadOptions.enable_materials = True
Adegan dimuat tetapi semua node kosongFile menggunakan format FBXParser FBX sedang dalam pengembangan; gunakan OBJ, STL, atau glTF sebagai gantinya
Model sangat kecil atau sangat besarFile sumber menggunakan satuan non-metrikTerapkan ObjLoadOptions.scale untuk mengonversi ke satuan target Anda
AttributeError aktif mesh.polygonsEntitas node bukan MeshLindungi dengan if node.entity is not None sebelum mengakses properti entitas
File GLB ditolak oleh penampilDisimpan dengan .gltf ekstensiGunakan .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 untuk open(), from_file(), dan save().
  • Node: Node pohon dalam grafik adegan. Membawa entity, transform, global_transform, material, child_nodes, dan name.
  • 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 dengan control_points (daftar vertex) dan polygons.
  • 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 dengan diffuse_color dan emissive_color.
  • PhongMaterial: Menambahkan model shading spekular specular_color dan shininess.

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 dengan from_angle_axis() : dan to_matrix().
  • Matrix4: matriks transformasi 4×4.
  • BoundingBox: Kotak pembatas yang sejajar sumbu dengan minimum : dan maximum : 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 sebuah Node.
  • Light: Entitas sumber cahaya, dapat dipasang ke Node.
 Bahasa Indonesia