Функции и возможности
Aspose.3D FOSS for TypeScript — это библиотека Node.js с лицензией MIT для загрузки, построения и экспорта 3D‑сцен. Она поставляется с полными определениями типов TypeScript и единственной runtime‑зависимостью (xmldom), и поддержкой шести основных форматов 3D‑файлов. Эта страница является основным справочником по всем областям функций и содержит исполняемые примеры кода TypeScript для каждой из них.
Установка и настройка
Установите пакет из npm с помощью одной команды:
npm install @aspose/3dПакет ориентирован на CommonJS и требует Node.js 18 или новее. После установки проверьте, что ваш tsconfig.json включает следующие параметры компилятора для полной совместимости:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true
}
}Импортировать основной Scene класс из корня пакета. Классы параметров, специфичных для формата, импортируются из их соответствующих подпутей:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';Функции и возможности
Поддержка форматов
Aspose.3D FOSS for TypeScript читает и записывает шесть основных форматов 3D‑файлов. При загрузке определение формата происходит автоматически по бинарным магическим числам, поэтому вам не нужно явно указывать исходный формат.
| Формат | Чтение | Написать | Заметки |
|---|---|---|---|
| OBJ (Wavefront) | Да | Да | Читает/записывает .mtl материалы; используйте ObjLoadOptions.enableMaterials для импорта |
| glTF 2.0 | Да | Да | Текстовый формат JSON; материалы PBR |
| GLB | Да | Да | Бинарный glTF; установлен GltfSaveOptions.binaryMode = true |
| STL | Да | Да | Бинарный и ASCII; полный раундтрип проверен |
| 3MF | Да | Да | 3D Manufacturing Format with color and material metadata |
| FBX | Нет* | Нет* | Импортёр/экспортер существует, но автоматическое определение формата не подключено |
| COLLADA (DAE) | Да | Да | Масштабирование единиц, геометрия, материалы и анимационные клипы |
Загрузка OBJ с материалами:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const scene = new Scene();
const options = new ObjLoadOptions();
options.enableMaterials = true;
options.flipCoordinateSystem = false;
options.scale = 1.0;
options.normalizeNormal = true;
scene.open('model.obj', options);Сохранение в GLB (binary glTF):
import { Scene } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
// ... build or load scene content
const opts = new GltfSaveOptions();
opts.binaryMode = true;
scene.save('output.glb', GltfFormat.getInstance(), opts);Граф сцены
Весь 3D‑контент организован в виде дерева Node объектов, корневых в scene.rootNode. Каждый узел может нести Entity (a Mesh, Camera, Light, или другой SceneObject) и Transform который позиционирует его относительно родителя.
Ключевые классы графа сцены:
Scene: контейнер верхнего уровня; содержитrootNodeиanimationClipsNode: именованный узел дерева сchildNodes,entity,transform, иmaterialsEntity: базовый класс для присоединяемых объектов (Mesh,Camera,Light)SceneObject: базовый класс, общий дляNodeиEntityA3DObject: корневой базовый класс сnameи набор свойствTransform: локальный перенос, вращение (Эйлера и кватерниона), и масштаб
Обход графа сцены:
import { Scene, Node, Mesh } from '@aspose/3d';
const scene = new Scene();
scene.open('model.obj');
function visit(node: Node, depth: number = 0): void {
const indent = ' '.repeat(depth);
console.log(`${indent}Node: ${node.name}`);
if (node.entity) {
console.log(`${indent} Entity: ${node.entity.constructor.name}`);
}
for (const child of node.childNodes) {
visit(child, depth + 1);
}
}
visit(scene.rootNode);Создание иерархии сцены программно:
import { Scene, Node } from '@aspose/3d';
const scene = new Scene();
const parent = scene.rootNode.createChildNode('chassis');
const wheel = parent.createChildNode('wheel_fl');
wheel.transform.translation.set(0.9, -0.3, 1.4);Геометрия и Mesh
Mesh является основным типом геометрии. Он расширяет Geometry и предоставляет контрольные точки (вершины), индексы полигонов и элементы вершин для нормалей, UVs и цветов вершин.
Ключевые классы геометрии:
Mesh: полигональная сетка сcontrolPointsиpolygonCountGeometry: базовый класс с управлением элементами вершинVertexElementNormal: нормали per-vertex или per-polygon-vertexVertexElementUV: текстурные координаты (один или несколько UV-каналов)VertexElementVertexColor: цветовые данные per-vertexMappingMode: управляет тем, как данные элементов сопоставляются с полигонамиCONTROL_POINT,POLYGON_VERTEX,POLYGON,EDGE,ALL_SAME)ReferenceMode: управляет стратегией индексации (DIRECT,INDEX,INDEX_TO_DIRECT)VertexElementType: определяет семантику элемента вершиныTextureMapping: перечисление каналов текстуры
Чтение данных сетки из загруженной сцены:
import { Scene, Mesh, VertexElementType } from '@aspose/3d';
const scene = new Scene();
scene.open('model.stl');
for (const node of scene.rootNode.childNodes) {
if (node.entity instanceof Mesh) {
const mesh = node.entity as Mesh;
console.log(`Mesh "${node.name}": ${mesh.controlPoints.length} vertices, ${mesh.polygonCount} polygons`);
const normals = mesh.getElement(VertexElementType.NORMAL);
if (normals) {
console.log(` Normal mapping: ${normals.mappingMode}`);
}
}
}Система материалов
Aspose.3D FOSS для TypeScript поддерживает три типа материалов, охватывающих весь спектр от устаревшего Phong shading до физически‑корректного рендеринга:
LambertMaterial: диффузный цвет и окружающий цвет; отображается на простые материалы OBJ/DAEPhongMaterial: добавляет specular color, shininess и emissive; тип материала по умолчанию для OBJPbrMaterial: физически‑основанная модель roughness/metallic; используется для импорта и экспорта glTF 2.0
Чтение материалов из загруженной сцены OBJ:
import { Scene, PhongMaterial, LambertMaterial } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const scene = new Scene();
const options = new ObjLoadOptions();
options.enableMaterials = true;
scene.open('model.obj', options);
for (const node of scene.rootNode.childNodes) {
for (const mat of node.materials) {
if (mat instanceof PhongMaterial) {
const phong = mat as PhongMaterial;
console.log(` Phong: diffuse=${JSON.stringify(phong.diffuseColor)}, shininess=${phong.shininess}`);
} else if (mat instanceof LambertMaterial) {
console.log(` Lambert: diffuse=${JSON.stringify((mat as LambertMaterial).diffuseColor)}`);
}
}
}Применение PBR‑материала при построении сцены glTF:
import { Scene, Node, PbrMaterial } from '@aspose/3d';
import { Vector3 } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
const node = scene.rootNode.createChildNode('sphere');
const mat = new PbrMaterial();
mat.albedo = new Vector3(0.8, 0.2, 0.2); // red-tinted albedo; albedo starts null, must assign
mat.metallicFactor = 0.0;
mat.roughnessFactor = 0.5;
node.material = mat;
const opts = new GltfSaveOptions();
opts.binaryMode = false;
scene.save('output.gltf', GltfFormat.getInstance(), opts);Математические утилиты
Библиотека поставляется с полным набором 3D‑математических типов, все полностью типизированы:
Vector3: 3-component vector; поддерживаетminus(),times(),dot(),cross(),normalize(),length,angleBetween()Vector4: 4-component vector для однородных координатMatrix4: 4×4 матрица преобразования сconcatenate(),transpose,decompose,setTRSQuaternion: кватернион вращения сfromEulerAngle()(статический, единственный),eulerAngles()(метод экземпляра),slerp(),normalize()BoundingBox: ограничивающий параллелепипед, выровненный по осям, сminimum,maximum,center,size,mergeFVector3: вариант одинарной точностиVector3: используется в данных элементов вершин
Вычисление ограничивающего параллелепипеда из вершин меша:
import { Scene, Mesh, Vector3, BoundingBox } from '@aspose/3d';
const scene = new Scene();
scene.open('model.obj');
let box = new BoundingBox();
for (const node of scene.rootNode.childNodes) {
if (node.entity instanceof Mesh) {
for (const pt of (node.entity as Mesh).controlPoints) {
box.merge(new Vector3(pt.x, pt.y, pt.z));
}
}
}
console.log('Center:', box.center);
console.log('Extents:', box.size);Построение трансформации из углов Эйлера:
import { Quaternion, Vector3, Matrix4 } from '@aspose/3d';
const rot = Quaternion.fromEulerAngle(0, Math.PI / 4, 0); // 45° around Y
const mat = new Matrix4();
mat.setTRS(new Vector3(0, 0, 0), rot, new Vector3(1, 1, 1));Система анимации
API анимации моделирует клипы, узлы, каналы и последовательности ключевых кадров:
AnimationClip: именованная коллекция узлов анимации; доступ к которой осуществляется черезscene.animationClips; раскрываетanimations: AnimationNode[]AnimationNode: именованная группаBindPoints; создано черезclip.createAnimationNode(name), доступно черезclip.animationsBindPoint: привязываетAnimationNode: к конкретному свойству объекта сцены; раскрываетproperty: иchannelsCountAnimationChannel: расширяетKeyframeSequence; содержит отдельныйkeyframeSequence; доступен черезbindPoint.getChannel(name)KeyFrame: одна пара время/значение; несёт per-keyframeinterpolation: InterpolationKeyframeSequence: упорядоченный списокKeyFrameобъекты черезkeyFrames; имеетpreBehaviorиpostBehavior(Extrapolation)Interpolation: enum:LINEAR,CONSTANT,BEZIER,B_SPLINE,CARDINAL_SPLINE,TCB_SPLINEExtrapolation: класс сtype: ExtrapolationTypeиrepeatCount: numberExtrapolationType: enum:CONSTANT,GRADIENT,CYCLE,CYCLE_RELATIVE,OSCILLATE
Чтение анимационных данных из загруженной сцены:
import { Scene, AnimationNode, BindPoint } from '@aspose/3d';
const scene = new Scene();
scene.open('animated.dae'); // COLLADA animation import is supported
for (const clip of scene.animationClips) {
console.log(`Clip: "${clip.name}"`);
for (const animNode of clip.animations) { // clip.animations, not clip.nodes
console.log(` AnimationNode: ${animNode.name}`);
for (const bp of animNode.bindPoints) { // animNode.bindPoints, not animNode.channels
console.log(` BindPoint: property="${bp.property.name}", channels=${bp.channelsCount}`);
}
}
}Поддержка потоков и буферов
Использовать scene.openFromBuffer() загрузить 3D сцену напрямую из оперативной памяти Buffer. Это рекомендуемый шаблон для безсерверных функций, потоковых конвейеров и обработки ресурсов, полученных по HTTP без записи на диск.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import * as fs from 'fs';
// Load file into memory, then parse from buffer
const buffer: Buffer = fs.readFileSync('model.obj');
const scene = new Scene();
const options = new ObjLoadOptions();
options.enableMaterials = true;
scene.openFromBuffer(buffer, options);
for (const node of scene.rootNode.childNodes) {
if (node.entity) {
console.log(node.name, node.entity.constructor.name);
}
}Автоматическое определение формата по бинарным магическим числам работает при загрузке из буфера, поэтому файлы GLB, бинарный STL и 3MF распознаются без указания параметра формата.
Примеры использования
Пример 1: загрузка OBJ и экспорт в GLB
В этом примере загружается файл Wavefront OBJ с материалами, после чего сцена экспортируется в бинарный glTF (GLB), пригодный для использования в вебе и игровых движках.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
function convertObjToGlb(inputPath: string, outputPath: string): void {
const scene = new Scene();
const loadOpts = new ObjLoadOptions();
loadOpts.enableMaterials = true;
loadOpts.flipCoordinateSystem = false;
loadOpts.normalizeNormal = true;
scene.open(inputPath, loadOpts);
// Report what was loaded
for (const node of scene.rootNode.childNodes) {
if (node.entity) {
console.log(`Loaded: ${node.name} (${node.entity.constructor.name})`);
}
}
const saveOpts = new GltfSaveOptions();
saveOpts.binaryMode = true; // write .glb instead of .gltf + .bin
scene.save(outputPath, GltfFormat.getInstance(), saveOpts);
console.log(`Exported GLB to: ${outputPath}`);
}
convertObjToGlb('input.obj', 'output.glb');Пример 2: круговой проход STL с проверкой нормалей
В этом примере загружается бинарный файл STL, выводится информация о нормалях для каждой вершины, затем сцена экспортируется в ASCII STL и проверяется корректность обратного преобразования.
import { Scene, Mesh, VertexElementNormal, VertexElementType } from '@aspose/3d';
import { StlLoadOptions, StlSaveOptions } from '@aspose/3d/formats/stl';
const scene = new Scene();
const loadOpts = new StlLoadOptions();
scene.open('model.stl', loadOpts);
let totalPolygons = 0;
for (const node of scene.rootNode.childNodes) {
if (node.entity instanceof Mesh) {
const mesh = node.entity as Mesh;
totalPolygons += mesh.polygonCount;
const normElem = mesh.getElement(VertexElementType.NORMAL) as VertexElementNormal | null;
if (normElem) {
console.log(` Normals: ${normElem.data.length} entries, mapping=${normElem.mappingMode}`);
}
}
}
console.log(`Total polygons: ${totalPolygons}`);
// Re-export as ASCII STL
const saveOpts = new StlSaveOptions();
saveOpts.binaryMode = false; // ASCII output
scene.save('output_ascii.stl', saveOpts);Пример 3: Создать сцену программно и сохранить как glTF
Этот пример создает сцену с PBR‑материалом с нуля и сохраняет её как JSON‑файл glTF.
import { Scene, Mesh, PbrMaterial, Vector4, Vector3 } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
const node = scene.rootNode.createChildNode('floor');
// Build a simple quad mesh (two triangles)
// controlPoints are Vector4 (x, y, z, w) where w=1 for positions
const mesh = new Mesh();
mesh.controlPoints.push(
new Vector4(-1, 0, -1, 1),
new Vector4( 1, 0, -1, 1),
new Vector4( 1, 0, 1, 1),
new Vector4(-1, 0, 1, 1),
);
mesh.createPolygon([0, 1, 2]);
mesh.createPolygon([0, 2, 3]);
node.entity = mesh;
// Apply a PBR material
const mat = new PbrMaterial();
mat.albedo = new Vector3(0.6, 0.6, 0.6); // albedo starts null, must assign
mat.metallicFactor = 0.0;
mat.roughnessFactor = 0.8;
node.material = mat;
// Save as JSON glTF
const opts = new GltfSaveOptions();
opts.binaryMode = false;
scene.save('floor.gltf', GltfFormat.getInstance(), opts);
console.log('Scene written to floor.gltf');Советы и лучшие практики
- Используйте
ObjLoadOptions.enableMaterials = trueкогда вам нужны данные материалов из файлов .mtl. Без этого список материалов на каждом узле будет пустым. - Предпочитайте
binaryMode = trueдля GLB при создании ассетов для веб- или игровых движков. Бинарный GLB — это один автономный файл, который загружается быстрее в браузерах и движках, чем разделённые JSON + .bin. - Используйте
openFromBuffer()в безсерверных средах чтобы избежать временного ввода/вывода файлов. Получите ресурс, передайтеBufferнепосредственно и запишите вывод в поток или другой буфер. - Проверьте
node.entityперед приведением: не все узлы содержат сущность. Всегда проверяйте наличиеinstanceofпроверку перед доступомMesh-специфические свойства, такие какcontrolPoints. - Установить
normalizeNormal = trueвObjLoadOptionsкогда ваши исходные OBJ‑файлы поступают из ненадёжных источников. Это предотвращает распространение вырожденных нормалей в последующие этапы рендеринга или проверки. - Сохранить
strict: trueв tsconfig.json: библиотека написана сnoImplicitAnyиstrictNullChecks. Отключениеstrictмаскирует реальные ошибки типов и подрывает ценность типизированного API. - Обход через
childNodes, а не цикл по индексу: этоchildNodesсвойство возвращает итерируемый объект; избегайте полагаться на числовую индексацию для обеспечения совместимости в будущем.
Распространённые проблемы
| Симптом | Вероятная причина | Исправление |
|---|---|---|
| Список материалов пуст после загрузки OBJ | enableMaterials не задано | Установлено options.enableMaterials = true |
| Файл GLB содержит отдельный .bin‑sidecar | binaryMode по умолчанию false | Установить opts.binaryMode = true |
| Нормали вершин отсутствуют в выводе STL | Режим STL ASCII опускает нормали граней | Переключиться на binaryMode = true или вычислить нормали перед экспортом |
node.entity всегда null | Только обход rootNode, не его дочерних | Рекурсивно в node.childNodes |
| Ошибка TypeScript: свойство не существует | Старый @types кеш | Запустить npm install @aspose/3d снова; без отдельного @types требуется пакет |
openFromBuffer выбрасывает ошибку формата | Формат не может быть автоматически определён по magic | Передайте явный класс опций формата в качестве второго аргумента |
Часто задаваемые вопросы
Требует ли библиотека какие‑либо native addons или системные пакеты? Нет. Aspose.3D FOSS for TypeScript имеет единственную зависимость во время выполнения: xmldom, который представляет собой чистый JavaScript и устанавливается автоматически npm. Нет .node нативных аддонов и системных пакетов для установки.
Какие версии Node.js поддерживаются? Node.js 18, 20 и 22 LTS. Библиотека ориентирована на вывод CommonJS и использует языковые возможности ES2020 внутри.
Могу ли я использовать библиотеку в браузерном бандле (webpack/esbuild)? Библиотека ориентирована на Node.js и использует Node.js fs и Buffer API. Объединение в браузере официально не поддерживается. Для использования в браузере загрузите сцену на стороне сервера и передайте результат (например, в виде GLB) клиенту.
В чём разница между GltfSaveOptions.binaryMode = true и false? binaryMode = false создаёт a .gltf JSON‑файл плюс отдельный .bin двоичный буфер‑сайдкар. binaryMode = true создаёт один самодостаточный .glb файл. Используйте true для доставки производственных активов.
Могу ли я загрузить файл из HTTP-ответа, не сохраняя его на диск? Да. Получите ответ как Buffer (например, используя node-fetch или встроенный fetch в Node 18+), затем вызвать scene.openFromBuffer(buffer, options).
Поддержка FBX завершена? Нет. Классы импортёра и экспортёра FBX существуют в библиотеке, но FBX не подключён к Scene.open() или Scene.save() автоматическое определение. Вызов scene.open('file.fbx') не вызовет FBX importer; файл будет обработан резервным путём STL. Используйте классы FBX-specific importer/exporter напрямую, если вам нужен FBX I/O. См. таблицу поддержки форматов выше, где FBX отмечен как No*.
Поддерживает ли библиотека TypeScript 4.x? Рекомендуется TypeScript 5.0+. TypeScript 4.7+ должен работать на практике, но библиотека тестируется и разрабатывается под 5.0+.
Сводка справки API
| Класс | Модуль | Назначение |
|---|---|---|
Scene | @aspose/3d | Контейнер сцены верхнего уровня; open(), openFromBuffer(), save(), rootNode, animationClips |
Node | @aspose/3d | Узел графа сцены; childNodes, entity, transform, materials, createChildNode() |
Entity | @aspose/3d | Базовый класс для объектов, присоединяемых к сцене |
SceneObject | @aspose/3d | Базовый класс, общий для Node и Entity |
A3DObject | @aspose/3d | Корневая база с name и набор свойств |
Transform | @aspose/3d | Локальный перенос, вращение и масштаб |
Mesh | @aspose/3d | Полигональная сетка; controlPoints, polygonCount, createPolygon(), элементы вершин |
Geometry | @aspose/3d | Базовый класс для типов геометрии |
Camera | @aspose/3d | Сущность камеры с настройками угла обзора и проекции |
Light | @aspose/3d | Световой объект (point, directional, spot) |
LambertMaterial | @aspose/3d | Модель затенения Diffuse + ambient |
PhongMaterial | @aspose/3d | Затенение Phong с specular и emissive |
PbrMaterial | @aspose/3d | Физически основанная модель roughness/metallic для glTF |
Vector3 | @aspose/3d | 3-component double-precision vector |
Vector4 | @aspose/3d | 4-component vector for homogeneous math |
Matrix4 | @aspose/3d | 4×4 transformation matrix |
Quaternion | @aspose/3d | Кватернион вращения |
BoundingBox | @aspose/3d | Осиально-выравненный ограничивающий параллелепипед |
FVector3 | @aspose/3d | Вариант одинарной точности Vector3 |
VertexElementNormal | @aspose/3d | Нормали, задаваемые на каждую вершину или вершину полигона |
VertexElementUV | @aspose/3d | Элемент вершины текстурных координат |
VertexElementVertexColor | @aspose/3d | Элемент вершины цвета |
MappingMode | @aspose/3d | Enum: CONTROL_POINT, POLYGON_VERTEX, POLYGON, ALL_SAME |
ReferenceMode | @aspose/3d | Enum: DIRECT, INDEX, INDEX_TO_DIRECT |
AnimationClip | @aspose/3d | Именованная анимация; предоставляет animations: AnimationNode[]; создано через scene.createAnimationClip(name) |
AnimationNode | @aspose/3d | Именованная группа BindPoints; создано через clip.createAnimationNode(name) |
BindPoint | @aspose/3d | Привязывает AnimationNode к свойству объекта сцены; раскрывает property и channelsCount |
AnimationChannel | @aspose/3d | Расширяет KeyframeSequence; содержит keyframeSequence; доступен через bindPoint.getChannel(name) |
KeyFrame | @aspose/3d | Один парный кадр времени/значения; несёт interpolation: Interpolation |
KeyframeSequence | @aspose/3d | Упорядоченный keyFrames список; preBehavior/postBehavior являются Extrapolation объекты |
Interpolation | @aspose/3d | Enum: LINEAR, CONSTANT, BEZIER, B_SPLINE, CARDINAL_SPLINE, TCB_SPLINE |
Extrapolation | @aspose/3d | Класс с type: ExtrapolationType и repeatCount: number |
ExtrapolationType | @aspose/3d | Enum: CONSTANT, GRADIENT, CYCLE, CYCLE_RELATIVE, OSCILLATE |
ObjLoadOptions | @aspose/3d/formats/obj | Опции импорта OBJ: enableMaterials, flipCoordinateSystem, scale, normalizeNormal |
GltfSaveOptions | @aspose/3d/formats/gltf | Параметры экспорта glTF/GLB: binaryMode |
GltfFormat | @aspose/3d/formats/gltf | Экземпляр формата для glTF/GLB; передать в scene.save() |
StlLoadOptions | @aspose/3d/formats/stl | Параметры импорта STL |
StlSaveOptions | @aspose/3d/formats/stl | Параметры экспорта STL: binaryMode |
StlImporter | @aspose/3d/formats/stl | Низкоуровневый читатель STL |
StlExporter | @aspose/3d/formats/stl | Низкоуровневый записыватель STL |