Функції та можливості
Aspose.3D FOSS для Python надає повний API графу сцени для читання, створення та запису 3D‑контенту у кількох промислових стандартних форматах. Ця сторінка документує кожну основну область функціональності з робочими прикладами коду Python, які використовують реальний API бібліотеки.
Встановлення та налаштування
Встановіть бібліотеку з PyPI за допомогою однієї команди:
pip install aspose-3d-fossНе потрібні додаткові системні пакети, нативні розширення або інструментальні ланцюги компілятора. Бібліотека є чистим Python і підтримує Python 3.7‑3.12 на Windows, macOS та Linux.
Щоб перевірити встановлення:
from aspose.threed import Scene
scene = Scene()
print("Aspose.3D FOSS installed successfully")
print(f"Root node name: {scene.root_node.name}")Функції та можливості
Підтримка форматів
Aspose.3D FOSS для Python читає та записує наступні формати:
| Формат | Розширення | Читати | Записати | Примітки |
|---|---|---|---|---|
| Wavefront OBJ | .obj | Так | Так | .mtl завантаження матеріалів підтримується |
| STL (бінарний) | .stl | Так | Так | Круговий прохід підтверджено (39 тестів) |
| STL (ASCII) | .stl | Так | Так | Круговий прохід підтверджено |
| glTF 2.0 | .gltf | Так | Так | Повний граф сцени збережено |
| GLB (binary glTF) | .glb | Так | Так | Однофайловий бінарний контейнер |
| COLLADA | .dae | Так | Так | Ієрархія сцени та матеріали |
| 3MF | .3mf | Так | Так | Формат адитивного виробництва |
| FBX | .fbx | Частковий | Ні | Токенізатор працює; парсер має відомі помилки |
Завантаження OBJ з параметрами
ObjLoadOptions керує тим, як парсуються файли OBJ:
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")Збереження у STL
StlSaveOptions керує бінарним та ASCII виводом і іншими налаштуваннями, специфічними для STL:
from aspose.threed import Scene
from aspose.threed.formats import StlSaveOptions
scene = Scene.from_file("model.obj")
options = StlSaveOptions()
scene.save("output.stl", options)Граф сцени
Весь 3D‑контент організовано у вигляді дерева Node об’єктів. Корінь дерева є scene.root_node. Кожен вузол може містити дочірні вузли та нести Entity (меш, камера або світло) плюс Transform.
Обхід ієрархії сцени
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)Програмне створення сцени
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")Перевірка GlobalTransform
GlobalTransform надає трансформацію у світовому просторі вузла після накопичення всіх трансформацій предків:
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}")Mesh API
The Mesh об’єкт надає доступ до даних геометрії, включаючи контрольні точки (вершини), полігони та елементи вершин для нормалей, UV‑координат і кольорів.
Читання геометрії 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)}")Доступ до елементів вершин
Елементи вершин містять дані для кожної вершини або полігона. Найпоширеніші елементи — це нормалі, UV‑координати, кольори вершин та групи згладжування:
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)}")Система матеріалів
Aspose.3D FOSS підтримує два типи матеріалів: LambertMaterial (дифузне затінення) і PhongMaterial (спекулярне затінення). Обидва завантажуються автоматично з .mtl файлів при використанні ObjLoadOptions з enable_materials = True.
Читання матеріалів з 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}")Призначення матеріалу програмно
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")Математичні утиліти
The aspose.threed.utilities модуль надає всі типи геометричної математики, необхідні для побудови та інспекції сцени.
| Клас | Призначення |
|---|---|
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 | Представлення обертання без гімбального блокування |
Matrix4 | 4×4 transformation matrix |
BoundingBox | Осьово-узгоджений обмежувальний короб з мінімальними/максимальними кутами |
Робота з трансформаціями
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}")Обчислення обмежувальної коробки
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})")Анімація
Aspose.3D FOSS надає модель анімації, засновану на AnimationClip, AnimationNode, KeyFrame, і KeyframeSequence. Дані анімації, збережені у завантажених файлах (glTF, COLLADA), доступні через ці об’єкти.
Читання анімаційних кліпів
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}")Параметри завантаження та збереження
Кожен підтримуваний формат має відповідний клас параметрів, який керує поведінкою парсингу та серіалізації.
| Клас | Формат | Ключові властивості |
|---|---|---|
ObjLoadOptions | OBJ | enable_materials, flip_coordinate_system, normalize_normal, scale |
StlSaveOptions | STL | Бінарний проти ASCII режиму виводу |
| (glTF використовує значення за замовчуванням) | glTF / GLB | Граф сцени та матеріали зберігаються автоматично |
Приклади використання
Приклад 1: Конвертація формату OBJ у STL
Конвертуйте файл OBJ (з матеріалами) у бінарний STL, виводячи статистику сітки під час процесу:
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")Приклад 2: Пакування пакетних файлів glTF у GLB
Перезапишіть каталог окремих файлів glTF + текстур у самодостатні бінарні файли GLB:
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)}")Приклад 3: Перевірка графа сцени та звіт про експорт
Пройдіться по графу сцени файлу COLLADA, зберіть статистику для кожної сітки та виведіть структурований звіт:
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}"
)Поради та кращі практики
Вибір формату
- glTF 2.0 / GLB є рекомендованим форматом обміну для сцен, що включають матеріали, анімації та складні ієрархії. Віддавайте перевагу GLB (бінарному) над glTF (текстовим + зовнішні файли) для портативності.
- STL є правильним вибором, коли споживач нижчого рівня — це слайсер, CAD‑інструмент або будь‑який інструмент, який потребує лише геометрії. STL не містить даних про матеріали чи анімацію.
- OBJ широко підтримується і є хорошим вибором, коли потрібно обмінюватися даними про матеріали зі старими інструментами. Завжди зберігайте файл .mtl разом з файлом .obj.
Системи координат
- Різні застосунки використовують різні конвенції правосторонності/лівосторонності. Встановіть
ObjLoadOptions.flip_coordinate_system = Trueпри імпорті OBJ‑файлів з інструментів, які використовують правосторонню систему координат, якщо ваш конвеєр очікує лівосторонні координати, і навпаки. - Перевірте конвенцію осей вихідного ресурсу перед застосуванням будь‑якого віддзеркалення. Двічі віддзеркалити призводить до некоректної геометрії.
Нормалізація
- Завжди встановлюйте
ObjLoadOptions.normalize_normal = Trueколи нижчий конвеєр очікує одиничні нормалі (наприклад, при передачі нормалей у шейдер або під час обчислень освітлення за допомогою скалярного добутку). Ненормалізовані нормалі з погано сформованих OBJ‑файлів викликають артефакти освітлення.
Продуктивність
- Завантажуйте файли один раз і трансформуйте граф сцени в пам’яті, замість того щоб перезавантажувати їх з диска для кожного формату виводу. Одна
Scene.from_file()виклик, після якого слідує кількаscene.save()виклики ефективніші, ніж повторні завантаження. - При обробці великих пакетів створюйте один
ObjLoadOptionsабоStlSaveOptionsекземпляр і повторно використовуйте його для всіх файлів замість створення нового об’єкта параметрів для кожного файлу.
Обробка помилок
- Обгорніть
scene.open()іscene.save()виклики вtry/exceptблоки під час обробки ненадійних або наданих користувачем файлів. Вказуйте ім’я файлу в повідомленнях про виключення, щоб спростити налагодження у пакетних конвеєрах.
Поширені проблеми
| Проблема | Причина | Вирішення |
|---|---|---|
| Сітка відображається дзеркально після завантаження | Невідповідність орієнтації системи координат | Перемикач ObjLoadOptions.flip_coordinate_system |
| Нормалі нульової довжини | Вихідний файл містить ненормалізовані нормалі | Встановити ObjLoadOptions.normalize_normal = True |
| Матеріали не завантажені з OBJ | enable_materials є False (за замовчуванням) | Встановити ObjLoadOptions.enable_materials = True |
| Сцена завантажується, але всі вузли порожні | Файл використовує формат FBX | Парсер FBX у розробці; використовуйте OBJ, STL або glTF замість цього |
| Модель надзвичайно мала або велика | Вихідний файл використовує неметричні одиниці | Застосувати ObjLoadOptions.scale для перетворення у вашу цільову одиницю |
AttributeError на mesh.polygons | Сутність вузла не є Mesh | Захистити за допомогою if node.entity is not None перед доступом до властивостей сутності |
| Файл GLB відхилено переглядачем | Збережено за допомогою .gltf розширення | Використовуйте .glb розширення під час виклику scene.save() для запуску бінарного контейнера |
Часті запитання
Які версії Python підтримуються? Python 3.7, 3.8, 3.9, 3.10, 3.11 та 3.12 усі підтримуються. Бібліотека є чистим Python без нативних розширень, тому вона працює на будь‑якій платформі, де працює CPython.
Чи має бібліотека зовнішні залежності? Ні. Aspose.3D FOSS для Python лише використовує стандартну бібліотеку Python. Встановлюється як один pip install aspose-3d-foss команду без подальших кроків.
Чи підтримується FBX? Токенізатор FBX реалізовано і може розбирати бінарний потік токенів FBX, але будівник графа сцени поверх токенізатора має відомі помилки і не готовий до продакшн-використання. Використовуйте OBJ, STL, glTF, COLLADA або 3MF для надійного продакшн-використання.
Чи можу я використовувати Aspose.3D FOSS у комерційному продукті? Так. Бібліотека випущена під ліцензією MIT, яка дозволяє використання у пропрієтарному та комерційному програмному забезпеченні без виплат роялті, за умови включення повідомлення про ліцензію.
Як повідомити про помилку або запросити формат? Відкрийте issue у репозиторії. Додайте мінімальний файл‑репродуктор та версію Python, операційну систему та версію бібліотеки з pip show aspose-3d-foss.
Огляд довідки API
Основні класи
Scene: Верхній контейнер 3D‑сцени. Точка входу дляopen(),from_file(), таsave().Node: Вузол дерева у графі сцени. Несеentity,transform,global_transform,material,child_nodes, таname.Entity: Базовий клас для об’єктів, приєднаних до вузлів (Mesh, Camera, Light).Transform: Позиція, обертання (Quaternion) та масштаб у локальному просторі для вузла.GlobalTransform: Трансформація у глобальному просторі лише для читання, обчислена шляхом накопичення трансформацій усіх предків.
Геометрія
Mesh: Полігональна сітка зcontrol_points(список вершин) іpolygons.VertexElementNormal: Вектор нормалі для кожної вершини або кожного полігона.VertexElementUV: UV-координати текстури для кожної вершини.VertexElementVertexColor: Колірні дані для кожної вершини.VertexElementSmoothingGroup: Призначення груп згладжування полігонів.
Матеріали
LambertMaterial: Модель дифузного затінення зdiffuse_colorіemissive_color.PhongMaterial: Додавання моделі відблискового затіненняspecular_colorіshininess.
Математичні утиліти (aspose.threed.utilities)
Vector2: 2D вектор.Vector3: 3D вектор з подвійною точністю.Vector4: 4D вектор з подвійною точністю.FVector3: 3D вектор з одинарною точністю.Quaternion: Кватерніон обертання зfrom_angle_axis()іto_matrix().Matrix4: 4×4 матриця перетворення.BoundingBox: Прямокутна обмежувальна коробка, орієнтована за осями, зminimumіmaximumкутами.
Анімація
AnimationClip: Іменований контейнер для набору анімаційних каналів та їх ключових кадрів.AnimationNode: Дані анімації для кожного вузла в межах кліпу.KeyFrame: Окремий ключовий кадр з часом і значенням.KeyframeSequence: Впорядкована послідовність ключових кадрів для однієї анімованої властивості.
Параметри завантаження / збереження
ObjLoadOptions: Налаштування завантаження, специфічні для OBJ:enable_materials,flip_coordinate_system,normalize_normal,scale.StlSaveOptions: Налаштування збереження, специфічні для STL (бінарний vs. ASCII режим).
Камери та світильники
Camera: Об’єкт камери з налаштуваннями проекції, який можна приєднати до aNode.Light: Об’єкт джерела світла, який можна приєднати до aNode.