Функции и возможности

Aspose.3D FOSS for 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 for 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 (mesh, camera, or light) плюс 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}")

API сетки

Этой Mesh entity предоставляет доступ к геометрическим данным, включая контрольные точки (vertices), полигоны и элементы вершин для нормалей, 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")

Математические утилиты

Эта aspose.threed.utilities module предоставляет все типы геометрической математики, необходимые для построения и инспекции сцены.

КлассНазначение
Vector22D floating-point vector (UV coordinates)
Vector33D double-precision vector (positions, normals)
Vector44D double-precision vector (homogeneous coordinates)
FVector33D single-precision vector (compact storage)
QuaternionПредставление вращения без гимбального замка
Matrix44×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}")

Параметры загрузки и сохранения

Каждый поддерживаемый формат имеет соответствующий класс параметров, который управляет поведением парсинга и сериализации.

КлассФорматКлючевые свойства
ObjLoadOptionsOBJenable_materials, flip_coordinate_system, normalize_normal, scale
StlSaveOptionsSTLБинарный vs. 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 (binary) вместо glTF (text + external files) для портативности.
  • STL является правильным выбором, когда downstream consumer — это слайсер, CAD‑инструмент или любой инструмент, которому нужна только геометрия. STL не содержит данных о материале или анимации.
  • OBJ широко поддерживается и является хорошим выбором, когда необходимо обмениваться данными о материале со старыми инструментами. Всегда храните файл .mtl рядом с файлом .obj.

Системы координат

  • Разные приложения используют разные конвенции правосторонности/левосторонности. Установите ObjLoadOptions.flip_coordinate_system = True при импорте OBJ‑файлов из инструментов, использующих правостороннюю систему координат, если ваш конвейер ожидает левосторонние координаты, и наоборот.
  • Проверьте конвенцию осей исходного ассета перед применением любого отражения. Двойное отражение приводит к некорректной геометрии.

Нормализация

  • Всегда устанавливайте ObjLoadOptions.normalize_normal = True если downstream pipeline ожидает нормализованные векторы нормалей (например, при передаче нормалей в шейдер или при вычислениях освещения с помощью скалярного произведения). Ненормализованные нормали из плохо сформированных OBJ‑файлов вызывают артефакты освещения.

Производительность

  • Загружайте файлы один раз и преобразуйте граф сцены в памяти, а не пере‑загружайте их с диска для каждого формата вывода. Один единственный Scene.from_file() вызов, за которым следуют множественные scene.save() вызовы более эффективны, чем повторные загрузки.
  • При обработке больших пакетов создавайте один единственный ObjLoadOptions или StlSaveOptions экземпляр и переиспользуйте его для всех файлов, вместо создания нового объекта параметров для каждого файла.

Обработка ошибок

  • Оборачивайте scene.open() и scene.save() вызовы в try/except блоки при обработке недоверенных или пользовательских файлов. Указывайте имя файла в сообщениях об исключениях, чтобы упростить отладку в пакетных конвейерах.

Распространённые проблемы

ПроблемаПричинаРешение
Сетка отображается зеркально после загрузкиНесоответствие правосторонности системы координатПереключить ObjLoadOptions.flip_coordinate_system
Нормали нулевой длиныИсходный файл содержит ненормализованные нормалиУстановить ObjLoadOptions.normalize_normal = True
Материалы не загружены из OBJenable_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: Трансформ в мировом пространстве только для чтения, вычисляемый путём накопления трансформов всех предков.

Geometry

  • 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: Сущность камеры с настройками проекции, присоединяемая к a Node.
  • Light: Сущность источника света, присоединяемая к a Node.
 Русский